当前位置:  开发笔记 > 编程语言 > 正文

为什么C字符文字而不是字符?

如何解决《为什么C字符文字而不是字符?》经验,为你挑选了7个好方法。

在C++中sizeof('a') == sizeof(char) == 1.这具有直观意义,因为它'a'是一个字符文字,并且sizeof(char) == 1由标准定义.

然而,在C中sizeof('a') == sizeof(int).也就是说,看起来C字符文字实际上是整数.有谁知道为什么?我可以找到很多关于这个C怪癖的提及,但没有解释为什么它存在.



1> Malx..:

关于同一主题的讨论

"更具体地说,整体促销.在K&R C中,如果不首先将字符值提升为int,则几乎不可能使用字符值,因此首先使字符常量int消除了该步骤.已经存在并且仍然是多字符诸如'abcd'之类的常量或者许多常量都适合于int."


我会注意到a)这个报价是未归因的; 引用只是说"你会不同意这个意见,这个意见是在过去讨论有关问题的帖子中发布的?" ...和b)它是**荒谬的**,因为`char`变量不是int,所以使一个字符常量为1就是一个特例.并且很容易使用字符值而不提升它:`c1 = c2;`.OTOH,`c1 ='x'`是向下转换.最重要的是,`sizeof(char)!= sizeof('x')`,这是严重的语言问题.至于多字节字符常量:它们是原因,但它们已经过时了.

2> John Vincent..:

最初的问题是"为什么?"

原因是文字字符的定义已经发生变化,同时试图保持向后兼容现有代码.

在早期的黑暗时期,根本没有类型.当我第一次学习用C语言编程时,已经引入了类型,但函数没有原型来告诉调用者参数类型是什么.相反,标准化的是,作为参数传递的所有内容都将是int的大小(包括所有指针)或者它将是double.

这意味着当你编写函数时,所有不是double的参数都以int的形式存储在堆栈中,无论你如何声明它们,编译器都会在函数中放置代码来为你处理这个问题.

这使得事情有些不一致,所以当K&R写出他们着名的书时,他们会在字符文字中始终将其提升为任何表达式中的int,而不仅仅是函数参数.

当ANSI委员会首次标准化C时,他们改变了这个规则,因此字符文字只是一个int,因为这似乎是实现同样事情的一种更简单的方法.

在设计C++时,所有函数都需要有完整的原型(C中仍然不需要这样做,尽管它被普遍认为是一种好的做法).因此,决定将字符文字存储在char中.这在C++中的优点是具有char参数的函数和具有int参数的函数具有不同的签名.这种优势不是C的情况.

这就是他们与众不同的原因.演化...


向我+1了,他们实际上回答了“为什么?”。但是我不同意最后一条语句-“在C ++中,这样做的优势在于,具有char参数的函数和具有int参数的函数具有不同的签名” –在C ++中,两个函数仍可能具有相同大小和不同的签名,例如`void f(unsigned char)`与`void f(signed char)`。
@PeterK约翰本可以把它变得更好,但他所说的基本上是准确的.C++更改的动机是,如果编写`f('a')`,您可能希望重载决策为该调用选择`f(char)`而不是`f(int)`.正如你所说,`int`和`char`的相对大小是无关紧要的.

3> Johannes Sch..:

我不知道C中字符文字的类型为int的具体原因.但是在C++中,有一个很好的理由不这样做.考虑一下:

void print(int);
void print(char);

print('a');

你会期望打印调用选择第二个版本的char.将字符文字作为int将使这不可能.请注意,在具有多个字符的C++文字中,仍然具有int类型,尽管它们的值是实现定义的.所以,'ab'有类型int,而'a'有类型char.


马克斯,是的,我作弊.我看了兼容性部分的标准:)

4> dmckee..:

在我的MacBook上使用gcc,我尝试:

#include 
#define test(A) do{printf(#A":\t%i\n",sizeof(A));}while(0)
int main(void){
  test('a');
  test("a");
  test("");
  test(char);
  test(short);
  test(int);
  test(long);
  test((char)0x0);
  test((short)0x0);
  test((int)0x0);
  test((long)0x0);
  return 0;
};

运行时给出:

'a':    4
"a":    2
"":     1
char:   1
short:  2
int:    4
long:   4
(char)0x0:      1
(short)0x0:     2
(int)0x0:       4
(long)0x0:      4

这表明一个字符是8位,就像你怀疑的那样,但字符文字是一个int.


+1有趣.人们通常认为sizeof("a")和sizeof("")是char*,应该给4(或8).但实际上它们在那时是char [](sizeof(char [11])给出了11).新手的陷阱.
字符文字不会提升为int,它已经是一个int.如果对象是sizeof运算符的操作数,则不会进行任何提升.如果有,这将失去sizeof的目的.

5> Tony Delroy..:

当C写入时,PDP-11的MACRO-11汇编语言有:

MOV #'A, R0      // 8-bit character encoding for 'A' into 16 bit register

这种事情在汇编语言中很常见 - 低8位将保存字符代码,其他位清零.PDP-11甚至具有:

MOV #"AB, R0     // 16-bit character encoding for 'A' (low byte) and 'B'

这提供了一种将两个字符加载到16位寄存器的低字节和高字节的便捷方法.然后,您可以在其他地方写入,更新一些文本数据或屏幕内存.

因此,将字符提升为寄存器大小的想法是非常正常和可取的.但是,假设您需要将'A'作为硬编码操作码的一部分放入寄存器中,而是从主存中的某处包含:

address: value
20: 'X'
21: 'A'
22: 'A'
23: 'X'
24: 0
25: 'A'
26: 'A'
27: 0
28: 'A'

如果你想从这个主存储器中只读一个'A'到一个寄存器,你会读到哪一个?

有些CPU可能只直接支持将16位值读入16位寄存器,这意味着在20或22处读取将需要清除"X"中的位,并且取决于CPU的字节序一个或其他需要转换到低位字节.

某些CPU可能需要内存对齐读取,这意味着所涉及的最低地址必须是数据大小的倍数:您可以从地址24和25读取,但不能读取27和28.

因此,编译器生成代码来获得一个"A"到寄存器可能更愿意浪费一点额外的内存和编码值为0"A"或"A" 0 - 根据字节序,以及确保其正确对齐(即不在奇数存储器地址).

我的猜测是C只是简单地将这种以CPU为中心的行为放在一边,考虑到占用内存寄存器大小的字符常量,将C的共同评估作为"高级汇编程序".

(参见http://www.dmv.net/dec/pdf/macro.pdf第6-25页的6.3.3 )



6> Kyle Cronin..:

我记得读过K&R并看到一个代码片段,它会一次读取一个角色,直到它达到EOF.由于所有字符都是文件/输入流中的有效字符,这意味着EOF不能是任何char值.代码所做的是将读取的字符放入int,然后测试EOF,如果不是则转换为char.

我意识到这并没有完全回答你的问题,但是如果EOF文字是,那么其余的字符文字就是sizeof(int).

int r;
char buffer[1024], *p; // don't use in production - buffer overflow likely
p = buffer;

while ((r = getc(file)) != EOF)
{
  *(p++) = (char) r;
}


@gbjbaanb:当然可以.这是空字符.想一想.你认为不应该允许文件包含任何零字节吗?
正如Malx所说 - EOF不是char类型 - 它是一个int类型.getchar()和朋友返回一个int,它可以保存任何char以及EOF而不会发生冲突.这实际上不需要文字字符类型为int.
EOF == -1在C的字符常量后很久就出现了,所以这不是一个答案,甚至不相关.

7> Michael Burr..:

我没有看到它的基本原理(C char文字是int类型),但这里是Stroustrup不得不说的东西(来自Design and Evolution 11.2.1 - Fine-Grain Resolution):

在C中,一个字符的文字的类型,例如'a'int.令人惊讶的是,在C++中赋予'a'类型char不会导致任何兼容性问题.除了病理学示例之外sizeof('a'),可以用C和C++表达的每个构造都给出相同的结果.

所以在大多数情况下,它应该没有问题.

推荐阅读
ERIK又
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有