c/c++语言开发共享&C中数组的运算符定义

最近的一个问题促成了以数组和指针为中心的讨论。 问题是参考scanf("%s", &name) vs scanf("%s", name)

对于以下代码,Microsoft实际上在VS2010(也许是早期版本?)中为您解决了这个问题,

 #include  int main() { char name[30]; printf("Scan "name" - "); scanf("%s", name); printf("Print "&name" - %sn", &name); printf("Print "name" - %sn", name); printf("Pointer to &name - %pn", &name); printf("Pointer to name - %pn", name); printf("nn"); printf("Scan "&name" - "); scanf("%s", &name); printf("Print "&name" - %sn", &name); printf("Print "name" - %sn", name); printf("Pointer to &name - %pn", &name); printf("Pointer to name - %pn", name); return 0; } 

这实际上是在ANSI C标准中定义的,还是允许编译器相关的? 这是否有效,因为MS将所有内容都视为C ++? 请暂时忽略缓冲区溢出问题。

    name&name都应该给出相同的结果。 严格来说,只有name根据C语言标准有效且&name导致未定义的行为,因此您绝对应该使用name ,但实际上两者都有效。

    name是一个数组,因此当你将它用作函数的参数时(就像你将它传递给printf ),它会“衰减”到指向其初始元素的指针(这里是一个char* )。

    &name为您提供数组的地址; 此地址与初始元素的地址相同(因为在数组的初始元素之前或数组中的元素之间不能有填充字节),因此&namename具有相同的指针值。

    但是,它们有不同的类型: &namechar (*)[30]类型char (*)[30] (指向30个char的数组的指针)而name ,当它衰减到指向其初始元素的指针时,类型为char* (指针)到一个char ,在这种情况下,是数组name的初始char元素)。

    由于它们具有相同的值,并且由于printfscanf函数无论如何都将参数重新解释为char* ,因此传递name&name应该没有区别。

    根据标准的未定义行为。

    printf转换说明符"%p"需要void* :其他任何内容调用UB printf转换说明符"%s"需要一个char* ,它包含指向对象内部某处的空字节:其他任何调用UB scanf转换说明符"%s"期望一个char*具有足够的空间用于输入和一个额外的空终止字节:其他任何东西调用UB

    如果任何实现定义了行为,那么在该实现中应该可以使用

    通常使用printf("%p")打印char*char(*)[30]而不是void*导致UB表现与预期行为无法区分。

    通常使用printf("%s")打印char(*)[30]而不是char*导致UB表现与预期行为无法区分。

    根据你的说法,在这些情况下,UB的MS表现与预期相同。

    但它仍然是未定义的行为。

    需要了解更多c/c++开发分享&C中数组的运算符定义,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!

      以上就是c/c++开发分享&C中数组的运算符定义相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/979541.html

      (0)
      上一篇 2021年12月13日
      下一篇 2021年12月13日

      精彩推荐