由于它不清楚什么是未定义的行为以及C中没有什么行为,我想知道使用char访问数组元素是否是未定义的行为。例如:
char c = 'A';
int a[3000];
printf("%i\n", a[c]);
我知道实际上字符和字符在某种程度上是可以互换的,但我仍然不确定。
答案 0 :(得分:1)
从语法上讲,a[c]
是一个有效的表达式,只要c
是整数类型或者可以提升为整数类型。
来自C99标准:
6.5.2.1数组下标
1其中一个表达式应具有类型''指向对象类型的指针'',另一个表达式应具有整数类型,结果具有类型''type''。
如果c
的值。 after被提升为int
,在数组的范围内,那么在运行时应该没有问题。
答案 1 :(得分:1)
使用char未定义的行为访问数组元素吗?
这不是未定义的行为。它像另一个整数类型一样工作。然而,char
的数值可能出人意料地为负数。
char
的范围与signed char
或unsigned char
的范围相同。它是实现定义。
如果提升的索引加上指针导致有效的内存地址,则使用c
作为索引是可以的。详情:char
将提升为int
,或可能提升为unsigned
。
如果c
具有负值,则可能存在以下问题。在OP的情况下,使用ASCII编码,'A'
的值为65,因此它没有0 <= 65 < 3000
的问题。 @Joachim Pileborg
char c = 'A';
int a[3000] = { 0 };
printf("%i\n", a[c]); // OK other than a[] not initialize in OP's code.
答案 2 :(得分:0)
据我所知,我说它并非未定义,而是定义得很好。原因是:char
可以被提升为integer
,这是一种索引数组的有效方法(或更好地说:指针,数组在该表达式中衰减)。索引与添加基本相同:
pointer + index // same as &(pointer[index]) or &(index[pointer])
并引用http://en.cppreference.com/w/cpp/language/implicit_cast(&#34;数字促销&#34;)
但是,[..]小积分类型(例如
char
)的Prvalues可以转换为更大整数类型的prvalues(例如int
)。特别是,算术运算符不接受小于int
的类型作为参数,[..]
AFAIK编译器会发出警告,因为通常你不会使用char
作为索引,因此编译器会尝试提供额外的安全网。
答案 3 :(得分:0)
它主要起作用,但要注意非ASCII字符,值为&gt; 127
如果char
已签名,它将被提升为否定整数,从而导致访问阵列外部的内存!
这是例如天真实施中的常见错误。 tolower()
答案 4 :(得分:0)
这应该自动转换为int并转到该数组的元素,因此行为不是未定义的。但是,从来没有真正有理由这样做。即使你从''(ASCII十进制值32)开始,你也没有使用之前的其他32个值。
我认为你可能正在尝试制作一个非常基本的哈希表。这可以通过结构和一些函数轻松完成;通常不好的做法是使用除整数类型之外的任何东西(即使char可以转换为int)作为数组下标。
答案 5 :(得分:0)
简短的回答是:代码片段无法编译。
中间答案是:如果函数定义的一部分,代码具有未定义的行为,因为它访问未初始化的对象。
答案很长:使用正确初始化的数组,它仍然取决于:
c
中的 a[c]
将被提升为int
,而C标准要求'A'
具有正值,无论类型char
是签名还是未签名。如果类型char
有8位,则行为不会被定义,但实现定义为'A'
的实际值取决于目标体系结构。
如果char
类型大于11位,则值'A'
可能会超过3000
,因此表达式可以尝试超出数组的结尾,具有未定义的行为。