使用char未定义的行为访问数组元素?

时间:2016-03-04 18:37:58

标签: c undefined-behavior

由于它不清楚什么是未定义的行为以及C中没有什么行为,我想知道使用char访问数组元素是否是未定义的行为。例如:

char c = 'A';
int a[3000];
printf("%i\n", a[c]);

我知道实际上字符和字符在某种程度上是可以互换的,但我仍然不确定。

6 个答案:

答案 0 :(得分:1)

从语法上讲,a[c]是一个有效的表达式,只要c是整数类型或者可以提升为整数类型。

来自C99标准:

  

6.5.2.1数组下标

     

1其中一个表达式应具有类型''指向对象类型的指针'',另一个表达式应具有整数类型,结果具有类型''type''。

如果c的值。 after被提升为int,在数组的范围内,那么在运行时应该没有问题。

答案 1 :(得分:1)

  

使用char未定义的行为访问数组元素吗?

这不是未定义的行为。它像另一个整数类型一样工作。然而,char的数值可能出人意料地为负数。

char的范围与signed charunsigned 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,因此表达式可以尝试超出数组的结尾,具有未定义的行为。