搜索
bottom↓
回复: 32

一个c语言问题:如何求一个字符串数组的元素个数?

[复制链接]

出0入0汤圆

发表于 2017-7-8 13:03:52 | 显示全部楼层 |阅读模式
比如一个 字符串数组
const char*Disp[]=
{
        {"temp"},
        {"vol"},
        {"light"},
};
每个字符串长度不一定相同。
如何在程序中计算它一共有多少的字符串?(比如这个例子有3个字符串)

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入4汤圆

发表于 2017-7-8 13:08:44 | 显示全部楼层
计算0X00的个数 也就是字符串结束符。

出0入0汤圆

发表于 2017-7-8 13:10:24 | 显示全部楼层
是没有办法的,这个文件等价于求任意一个数组元素个数

出0入147汤圆

发表于 2017-7-8 13:11:50 | 显示全部楼层
fbwcpu 发表于 2017-7-8 13:08
计算0X00的个数 也就是字符串结束符。

你试试,100% 跑飞。

出0入0汤圆

发表于 2017-7-8 13:14:49 | 显示全部楼层
其实这个数组存的是指针,也就是字符串的首地址。
元素个数和其它数组一样:
//求数组元素个数
#define ARRLEN(arr) (sizeof(arr)/sizeof(arr[0]))

出0入0汤圆

发表于 2017-7-8 13:15:53 来自手机 | 显示全部楼层
sizeof(Disp)/sizeof(Disp[0])

出0入4汤圆

发表于 2017-7-8 13:23:25 来自手机 | 显示全部楼层
六楼正解

出0入0汤圆

发表于 2017-7-8 13:51:27 来自手机 | 显示全部楼层
说下我对六楼的理解,sizeof(Disp)的结果应该是12,然后sizeof(Disp[0])的结果应该是4,那么最后计算的结果是3。不知道我理解的对不对

出0入0汤圆

发表于 2017-7-8 14:05:21 | 显示全部楼层
湛无双 发表于 2017-7-8 13:51
说下我对六楼的理解,sizeof(Disp)的结果应该是12,然后sizeof(Disp[0])的结果应该是4,那么最后计算的结果 ...

为何sizeof(disp[0])的结果是4?这个结果应该和编译环境有关吧。
sizeof(disp)可能也不是12吧。
六楼再给解惑一下比较好哦

出0入0汤圆

 楼主| 发表于 2017-7-8 14:10:46 | 显示全部楼层
at90s 发表于 2017-7-8 13:15
sizeof(Disp)/sizeof(Disp[0])

用VC 6.0试了,你的方法可行。
我准备到keil上看看

出0入0汤圆

 楼主| 发表于 2017-7-8 14:13:31 | 显示全部楼层
lcw_swust 发表于 2017-7-8 13:14
其实这个数组存的是指针,也就是字符串的首地址。
元素个数和其它数组一样:
//求数组元素个数

谢谢,可以用

出0入0汤圆

发表于 2017-7-8 14:53:00 | 显示全部楼层
本帖最后由 beihai326 于 2017-7-8 15:03 编辑
at90s 发表于 2017-7-8 13:15
sizeof(Disp)/sizeof(Disp[0])


32位机下面验证,是对的。

出0入4汤圆

发表于 2017-7-8 14:56:16 | 显示全部楼层
C/C++要求多维数组的每一维的长度必须一致

出0入0汤圆

发表于 2017-7-8 15:01:02 | 显示全部楼层
sizeof(变量名)

出0入0汤圆

发表于 2017-7-8 15:04:20 | 显示全部楼层
xiaobendan 发表于 2017-7-8 14:05
为何sizeof(disp[0])的结果是4?这个结果应该和编译环境有关吧。
sizeof(disp)可能也不是12吧。
六楼再给 ...

const char*Disp[]
定义一个数组,数组元素类型是const char*,即Disp是一个指针数组,数组里面每个指针指向字符串。所以sizeof(Disp)是这个数组的总字节数,sizeof(Disp[0])求得每个指针的字节数,注意是指针本身的字节数,不是指针指向的字符串字节数。

出0入0汤圆

发表于 2017-7-8 15:31:46 | 显示全部楼层
在C中,加上双引号的字符串都是'\0‘结尾的

出0入0汤圆

发表于 2017-7-8 16:21:43 | 显示全部楼层
lcw_swust 发表于 2017-7-8 13:14
其实这个数组存的是指针,也就是字符串的首地址。
元素个数和其它数组一样:
//求数组元素个数


sizeof是常量,类似于宏定义,编译时候固定死了,不知道符不符合楼主说的计算。。。比如楼主有个外挂FLASH,其中一段可以更新显示字符串,放了这个const char*Disp[]。。。   
如果不加其他的条件(比如数组最后填充一个0),楼主这个似乎无解。

出0入0汤圆

发表于 2017-7-8 16:24:28 | 显示全部楼层
如果是固定的,用sizeof跟用define常量一样了。

出0入0汤圆

发表于 2017-7-8 16:26:05 | 显示全部楼层
fbwcpu 发表于 2017-7-8 13:08
计算0X00的个数 也就是字符串结束符。

  最后运行到地老天荒

出0入10汤圆

发表于 2017-7-8 16:49:40 | 显示全部楼层
lcw_swust 发表于 2017-7-8 13:14
其实这个数组存的是指针,也就是字符串的首地址。
元素个数和其它数组一样:
//求数组元素个数

这位仁兄说得对,实际上,字符串、数字是常量,通常会防在flash中,你可以检查下map文件
实际上你提供的这个字符串数组的实际内容是{0xAAAAAAAA,0xBBBBBB,0xCCCCCCC},
这三个地址就是三个字符串的地址。

再举一个例子,int a=5;中,a是变量,放在ram中,但是掉电后,ram的内容会消失掉的,
那么为什么a还可以知道初始值是5,原因是5放在Flash中,复位的时候,会有代码将其
加载给a,所以a才有初始值为5。同理,上面有些坛友可能还不知道字符串也是常量,也是放
在Flash中,数组只是三个指针,指向Flash中存放三个字符串的地址。

出0入10汤圆

发表于 2017-7-8 16:51:51 | 显示全部楼层
sizeof(数组名)是数组的字节个数,sizeof(变量类型)是遍历类型的字节个数,因此有#define ARRLEN(arr) (sizeof(arr)/sizeof(arr[0]))

出0入0汤圆

 楼主| 发表于 2017-7-9 00:13:32 | 显示全部楼层
10xjzheng 发表于 2017-7-8 16:49
这位仁兄说得对,实际上,字符串、数字是常量,通常会防在flash中,你可以检查下map文件
实际上你提供的 ...

分析的很好,谢谢

出0入0汤圆

 楼主| 发表于 2017-7-9 00:16:11 | 显示全部楼层
huangqi412 发表于 2017-7-8 16:21
sizeof是常量,类似于宏定义,编译时候固定死了,不知道符不符合楼主说的计算。。。比如楼主有个外挂FLAS ...

还好我这个内容是定死的
如果是动态的,可能要其他数据结构了,比如链表

出0入22汤圆

发表于 2017-7-9 08:13:28 来自手机 | 显示全部楼层
凌晨一点 发表于 2017-7-9 00:16
还好我这个内容是定死的
如果是动态的,可能要其他数据结构了,比如链表 ...

动态的更好解决,因为你是动态的,所以代码必须知道长度,以便在添加和删除的时候找对位置。不然,跑飞...

出0入0汤圆

 楼主| 发表于 2017-7-9 12:49:39 | 显示全部楼层
zxq6 发表于 2017-7-9 08:13
动态的更好解决,因为你是动态的,所以代码必须知道长度,以便在添加和删除的时候找对位置。不然,跑飞.. ...

所谓动态,就是不知道长度和数量····

出0入22汤圆

发表于 2017-7-9 16:54:26 | 显示全部楼层
凌晨一点 发表于 2017-7-9 12:49
所谓动态,就是不知道长度和数量····

不知道长度和数量,这个,估计目前的编译器都没法处理你这个命题。

出200入2554汤圆

发表于 2017-7-9 18:15:03 | 显示全部楼层
先说几个结论,后续慢慢分析:

1. 使用 sizeof(Disp)/sizeof(Disp[0]) 就可以知道数组中元素(字串)的个数;

2. sizeof(Disp[0]) 大小是不定的,跟编译器有关,一般是 4,也有 2,如果有 XBOX 之类的话估计还有 8,详见后续验证;

3. 这个定义本质上是定义了三个字串指针,并且将三个字串地址赋值给这些指针,因而还是指针数组而非字串数组。




使用了两个编译器 ICCAVR_V2.22、VS2005 进行验证,首先是 ICCAVR 的,我查看了 MAP 文件、LST 文件,结果如下:

1. ICCAVR 的源文件,直接把 sizeof 付给了两个局部变量,实际分配的是 R16、R18 寄存器(8bit, unsigned char):


2. ICCAVR 的 MAP 文件,看到了 Disp 当中字符串的实际存储位置,注意这是指针指向的内容,而非指针本体:


3. ICCAVR 的 LST 文件,看到了直接的汇编动作,m=6, n=2,结果 sizeof(Disp)/sizeof(Disp[0]) =3,符合预期。
可以看到我在 ICCAVR 下的 sizeof(const char *) =2



接下来是 VS2005 的,直接打印输出就有了:

1. VS2005 源文件,直接拷贝数组定义:


2. VS2005 运行结果,看到 sizeof(Disp)=12, sizeof(Disp[0])=4,两者之商为 3,也符合预期。
很明显在 VS2005 当中 sizeof(const char *) =4



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2017-7-9 19:45:23 | 显示全部楼层
本帖最后由 湛无双 于 2017-7-9 19:51 编辑

楼上分析的正确,编译环境是VS2013的时候,在32位的条件下,程序如下:
  1. #include "stdio.h"
  2. const char*Disp[] =
  3. {
  4.         { "temp111" },
  5.         { "vol" },
  6.         { "light" },
  7. };
  8. const char temp[] = "temp1111";
  9. int main(void)
  10. {
  11.         printf("%d\n", sizeof(Disp));
  12.         printf("%d\n", sizeof(Disp[0]));
  13.         getch();
  14.         return 0;
  15. }
复制代码
编译结果如下:

说明在32位的平台下,sizeof(Disp)的大小为12,sizeof(Disp[0])的结果为4,那么最终结果为3。
接着更改为64位平台:

更改后的结果为:

可以发现在64的结果下,sizeof(Disp)的结果为24,sizeof(Disp[0])的结果为8,最终的结果还是3。
所以最终的结果与楼上的分析是符合的。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2017-7-9 20:42:05 来自手机 | 显示全部楼层
敬佩楼上两位的详细实践和分析

出0入0汤圆

发表于 2017-7-10 09:56:08 | 显示全部楼层
len=strlen(Disp);

出0入0汤圆

发表于 2017-7-10 09:56:49 | 显示全部楼层
len=strlen(&Disp[x]);

出0入0汤圆

发表于 2017-7-10 10:34:08 | 显示全部楼层
感谢分享:)

出0入0汤圆

发表于 2017-7-10 10:50:00 | 显示全部楼层
围观大师解答      
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-22 08:42

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表