【问题标题】:Char* array of chars, but int* not array of ints?Char* 字符数组,但 int* 不是整数数组?
【发布时间】:2015-09-18 03:27:40
【问题描述】:

在 C99 中,通常使用 char* 数据类型初始化字符串,因为没有原始的“字符串”数据类型。这通过将第一个字符的地址存储在变量中来有效地创建一个字符数组:

FILE* out = fopen("out.txt", "w");
char* s = argv[1];
fwrite(s, 12, 1, out);
fclose(out);
//successfully prints out 12 characters from argv[1] as a consecutive string.

编译器如何知道char* s 是一个字符串而不仅仅是一个单数char 的地址?如果我使用int*,它将只允许一个int,而不是它们的数组。为什么会有差异?

我的主要关注点是了解指针、引用和取消引用是如何工作的,但整个 char* 总是让我头疼。

【问题讨论】:

  • 编译器不知道char* s是一个字符串。 char* s 是指向 char 的指针,就像 int* s 是指向 int 的指针一样。只要我们到达最后一个'\0',我们就可以得到整个字符串。
  • "如果我使用 int* 它将只允许一个 int"。这不是真的。在 C 中,int* 可以用作数组。
  • @AlanAu:不,指针不能用作数组。
  • 数组和指针之间的关系可能会令人困惑。 comp.lang.c FAQ 的第 6 节很好地解释了它。
  • @AlanAu: i_array 是一个指针,而不是一个数组。 [] 运算符的前缀必须是指针(这通常是数组隐式转换的结果)。 (实际上[] 是可交换的,但这不是重点。)

标签: c arrays string pointers


【解决方案1】:

编译器如何知道char* s 是一个字符串而不仅仅是单个字符的地址?

它没有。就“编译器”而言,char* s 是一个指向 char 的指针。

另一方面,有许多库函数假定char* 指向null-terminated sequence of char 的元素(参见例如strlenstrcmp 等)。

请注意,fwrite 没有做出此假设。它要求你告诉它你想写入多少字节(并且这个数字不会让你超出第一个参数指向的缓冲区的范围。)

如果我使用int*,它将只允许一个 int,而不是它们的数组。为什么会有差异?

这是不正确的。 C 语言没有char* 的特殊情况。 int* 也可以指向int 数组的元素。实际上,您可以编写一个库,使用0 或其他标记值来指示int 序列的结束,并使用它与char* 的约定用法相同。

【讨论】:

  • 我看到了反对票。如果这个答案有什么问题,我想知道,以便我考虑修复它。
【解决方案2】:

在您的代码中

fwrite(s, 12, 1, out);

相当于写

从地址s开始写入12个大小为1字节的元素到out指向的文件。

这里。 char 正好是一个字节,所以你得到了想要的输出。

编译器如何知道char* s 是一个字符串而不仅仅是一个单数char 的地址?

嗯,它没有(也不需要)。您要求(从s 读取并)写入12 个字节,所以它会这样做。如果内存不可访问,那是一个编程错误。 fwrite() 本身不会处理

小心

  • 如果s 没有分配到s[11] 访问的内存(技术上),它将是undefined behaviour。程序员可以将 valid 值作为参数传递。

int 的情况下,大小为4 字节(通常在32 位系统上)并且逐字节打印不会给您想要的结果。

在这种情况下,您需要使用fprintf() 来打印格式化输出。

【讨论】:

    【解决方案3】:

    除了 char* 是字符的地址之外,编译器不会有任何想法。我们可以通过增加第一个字符的地址来使其读取后面的字符。这种情况类似于任何指针 int*、long* 等,编译器只是将指针视为指向其类型地址的东西。

    【讨论】:

      猜你喜欢
      • 2014-05-01
      • 2020-04-23
      • 1970-01-01
      • 2016-08-13
      • 1970-01-01
      • 2021-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多