【问题标题】:Passing string to an int variable in C?将字符串传递给C中的int变量?
【发布时间】:2021-04-01 07:36:42
【问题描述】:

这是一个将字符串“6”传递给整数变量y的程序

#include<stdio.h>
void main()
{
    int x=0;
    int y=0;
    if(x==1)
        y=20;
    if(x==4)
        y=25;
    if(x==0)
        y="6"+10+x+y;
    printf("y= %d",y);
}

这个程序的输出是y= 4206638,这意味着这里的“6”等于4206628。谁能告诉我“6”怎么等于4206628。 如果我将“6”替换为其他字符,则输出不受影响。

【问题讨论】:

  • 忽略 UB ...您误解了正在添加的内容...您无法添加整数和字符串,您的编译器假定您知道自己在做什么并添加(仍然忽略 UB)地址和整数.
  • "6"的值是存储的地址。它代表的数值是atoi("6"),但atoi()不太推荐。
  • 也许你想使用'6'
  • 你得到的是你转换成整数的字符串字面量的地址。您的编译器是否显示了一些警告?如果没有,请调高警告级别。对于 GCC,您可以使用 -Wall -Wextra 来实现。
  • 正如您在编辑之前提到的 cmets,您处理的是字符串的地址,而不是内容。更改内容不一定会更改地址。就像用新颜色粉刷你的前门不会改变你的居住地址一样。

标签: c string integer


【解决方案1】:
y="6"+10+x+y;

有了这行代码;字符串文字 "6" 的地址在内存中被分配给 int 对象 i,这在大多数情况下是 undefined 行为,因为在许多情况下,内存位置的值超出了对象的区域int 类型的可以容纳。

这个未定义的值然后被打印出来:

printf("y= %d",y);

此外,您会发现每次运行代码时值都不相同。 唯一的问题是,当它将指针转换为整数时,C 编译器不会将其视为错误,因为指针(内存中的地址)也是一个数字(尽管在大多数情况下,“地址数字”会溢出 int)并且您可以以您想要的任何格式打印:十进制、十六进制等。 此外,编译器必须在没有显式强制转换的情况下给您一个警告;比如:

warning: initialization of 'int' from 'char *' makes integer from pointer without a cast [-Wint-conversion]

道德:我们不应忽视智能编译器发出的警告。

【讨论】:

  • “C 编译器不将其视为错误” C 标准未定义术语“编译器错误”和“编译器警告”。请参阅What must a C compiler do when it finds an error? 在这种情况下,它必须 显示诊断消息。从指针到 int 的隐式转换是非标准扩展。
【解决方案2】:

问题是您要么使用了损坏的编译器,要么没有注意它。

"6" 是放在只读内存中的数组形式的字符串文字。该数组与任何数组一样,在用于表达式时“衰减”为指向第一个元素的指针。所以"6"+10+x+y 部分是指针算术(使用 1 字节字符),这反过来又超出了该数组的末尾并导致未定义的行为。

最后,您尝试将那个奇怪的无效指针分配给int。 C 语言不允许这样做,请参阅"Pointer from integer/integer from pointer without a cast" issues

地址会因不同系统而异。你可以运行这个定义明确的代码来亲自看看发生了什么:

#include<stdio.h>
#include <stdio.h>
#include <stdint.h>

int main()
{
    int x=0;
    int y=0;

    printf("%p (address of \"6\")\n", (void*)"6");
    printf("+ 0x%x\n", 10+x+y);
    printf("= 0x%x\n", (uintptr_t)"6"+10+x+y);
}

我得到这个输出:

0x402004 (address of "6")
+ 0xa
= 0x40200e

那么为什么编译器没有针对这个无效代码给你一个错误呢?原因:What must a C compiler do when it finds an error?

如果你是学习C的初学者,那么我强烈建议你这样编译(假设gcc/clang/icc):

gcc -std=c11 -pedantic-errors -Wall -Wextra -Werror

这将阻止损坏的 C 代码导致构建混乱、不正确的程序。

【讨论】:

    【解决方案3】:

    当您在 C 中定义字符串文字表达式时,将在只读内存中将字符串创建为数组,并将指针传递回应用程序。在这种情况下,存储在内存中的变量应该是一个 ASCII 数字 6,后跟一个空终止符(即 {0x36, 0x0})。但是,在您的程序中,您的表达式中使用的值实际上是该数组第一个元素的内存地址,因此看到 4206638 的值是有意义的。

    如果您希望在表达式中使用数字 6 (0x36) 的 ASCII 值,则应使用单引号(即“6”),这将返回一个有符号整数 0x36,这是6号。

    如果您希望在 C 中直接将字符串转换为整数,您可以使用标准库函数 atoi(),它接收字符串指针,例如应用程序中返回的字符串“6”的指针,以及返回一个有符号整数。

    【讨论】:

      猜你喜欢
      • 2020-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      • 1970-01-01
      • 1970-01-01
      • 2021-10-04
      相关资源
      最近更新 更多