使用malloc并执行类似的内存操作时,我可以依靠sizeof(char)始终为1吗?
例如,我需要为char类型的N个元素分配内存。 是否需要乘以sizeof( char ):
1
| char* buffer = malloc( N * sizeof( char ) ); |
或者我可以依靠sizeof(char)始终为1并跳过乘法
我完全理解sizeof是在编译期间求值的,然后编译器甚至可以编译出乘法,因此性能损失将最小并且很可能为零。
我主要是在询问代码的清晰度和可移植性。 char类型是否需要这种乘法?
根据定义,sizeof(char)始终等于1。一个字节是C语言中字符的大小,无论一个字节中的位数是多少(普通台式机CPU上为8)。
一个字节不是8位的典型示例是PDP-10和其他旧的,类似微型计算机的9/36位字节的体系结构。但是我相信不是2 ^ N的字节变得非常不常见
另外,我认为这是更好的样式:
1 2 3 4 5
| char* buf1 ;
double* buf2 ;
buf1 = malloc(sizeof(*buf1 ) * N );
buf2 = malloc(sizeof(*buf2 ) * N ); |
因为无论指针类型是什么,它都能工作。
-
我认为1Byte = 8位的定义。您是否有一个不适用的示例?
-
1个字节的定义为N位,其中N与机器有关。并非所有机器都有8位/字节(尽管这些天来没有这么多)
-
@AlexDrenea:今天,您通常只会遇到8位字节。但是字节的定义各不相同,并且与当今的体系结构无关,因为有些系统具有9位字节甚至36位字节。如果要确定,请使用ISO术语"八位字节"而不是字节。
不管您执行哪种类型的内存操作,sizeof(char)始终为1。
但是,sizeof(TCHAR)可能会有所不同,具体取决于您的编译器选项。
-
我不是专家,但是在unicode情况下字符的大小不会变大吗?
-
@影子,不。在这种情况下,通常使用宽字符类型wchar_t代替char。特定于Microsoft的TCHAR业务是一种编写可针对宽字符或窄字符进行编译的代码的方法。目前尚不清楚这是否是一个好主意。
-
@RBerteig:我想说清楚,这是个坏主意。在Windows上使用非宽char字符串的唯一原因是为了使可移植代码在其他符合标准的系统(POSIX)上也能正常工作。一旦编写TCHAR,您的代码就已经被Windows专用的东西污染了,您不妨直接使用它们的广泛功能和类型。用户尝试打开其中包含非代码页字符的文件名后,就不会有人希望其程序中断。
-
@R。实际上,TCHAR确实是一个可移植性障碍,它通过允许精心构造的代码进行编译而无需更改Win16,Win32 ASCII和Unicode Win32,从而使Windows 3.x程序员摆脱了8位char的困扰。在许多Windows API调用的上下文中使用它不会影响您的可移植性。但是,请勿将其用于应用程序处理的核心,否则您确实会影响可移植性。如果您确实避免使用API??使用TCHAR,请在编译时声明定义了UNICODE,并可能编写MessageBoxW而不是MessageBox等。
我认为这是一种反模式。这表明程序员不太了解他/她在做什么,这立即将其余代码转换为可疑状态。
当然,这并不是"无效"的(引用维基百科),但我确实发现它"远非最佳"。它在运行时不花任何钱,但它会使代码杂乱无章,同时始终表明有人认为有必要。
另外,请注意,表达式不会解析为函数调用:sizeof不是函数。您不是在调用传递神奇符号char的函数。您正在将内置的一元前缀运算符sizeof应用于表达式,在这种情况下,您的表达式是强制转换为类型char的类型,在C中用(char)表示。
完全有可能,并且强烈建议在其他表达式上使用sizeof,这将得出表达式值的大小:
1 2 3
| char a ;
printf("A char's size is %u
", (unsigned int) sizeof a ); |
这将始终在所有符合标准的C实现中打印1。
我也非常同意David Cournapeau的观点,并考虑在malloc() -call中重复键入类型名称,这也是一种反模式。
代替
1 2 3
| char *str ;
str = malloc(N * sizeof (char)); |
很多人会写来分配N个字符容量的字符串缓冲区,我会
1 2 3
| char *str ;
str = malloc(N * sizeof *str ); |
或者(仅对于字符串)忽略上述的sizeof,但是这当然是更通用的,并且对于任何类型的指针都一样有效。
-
我不同意。如果您忽略它,那么您(以及任何阅读您的代码的人)必须记住,这是一种特殊情况,并应如此。这增加了认知负担。有时,更多的代码会更好。
-
是的,sizeof不是一个函数-但对我来说,如果您将其视为一个函数,它会更容易阅读。除非您知道多余的括号会更改输出的情况?
-
@Michael Carman-这通常是一个特例,因为您经常分配和使用字符串,但是如果您要创建一个int数组,则可能是出于任何目的。我们需要将字符串与任意类型的数组区别对待,我发现malloc()中缺少sizeof(type)可以很好地提醒您这一点。
尽管没有必要,但我认为保留sizeof(char)是一种很好的做法,因为它使代码更易读并且避免使用幻数。另外,如果以后需要更改代码,以便将某个对象的大小分配给该对象的指针,而不是char,则比只有" 1"更容易更改代码。
-
这种"轻松更改代码"的说法很牛。 sizeof()是8个字符。必须添加它是因为有人没有写sizeof(char),然后将类型更改为wchar_t不会给任何人腕管,如果您担心这一点,则无论如何都应该使用sizeof *buf,因为它可以节省打字的次数。
-
@ChrisLutz,我正在看C11标准,但我没有看到任何专门说sizeof(char)是的子句。根据维基百科,它可以是任何东西:"例如,所有类型都可以是64位"。您能告诉我标准中的什么地方吗?
-
@Shahbaz-6.5.3.4第4段:"将sizeof应用于类型为char,unsigned char或signed char(或其限定版本)的操作数时,结果为1。"一直如此,一直如此。 char是C的"字节"。从语言的角度来看,char的位数无关紧要,它是最小的完整单位,并且所有sizeof值均以char s形式给出而不是"字节"(在C标准中不正确存在)。如果所有类型都是64位,则为sizeof(char) == sizeof(short) == sizeof(int) == sizeof(long) == 1,而不是8。
-
@ChrisLutz,谢谢,我正在查看char和其他类型本身的位置。当我们讨论这个问题时,我听说由于旧代码,他们将int的大小保持为4个字节,而不是让它像CPU一样大(就像long那样)。我还听说这发生在引入了long long的C99中。无论如何,这是正确的吗?如果对int和其他类型的大小有任何限制,那么该标准在哪里?
-
@Shahbaz-5.2.4.2.1列出了所有整数类型的最小大小。基本上,signed char必须至少能够表示127,signed short和signed int之间的所有数字,介于32767(或(2 ^ 15-1))之间,signed long在(2 ^ 31-1)之间,以及signed long long在(2 ^ 63-1)之间。因此,标准只要求int为2个字节。实际上,它的4个字节是因为"多数民众赞成在过去"(即使显然没有)。我认为他们实际上将int保留为4字节,因为否则类型将是4字节?如果将其设置为short,那么2个字节是什么类型?
-
@ChrisLutz,是的,您是对的。我以为他们已经对其进行了标准化,因此它是可靠的,但是我错了。谢谢您的帮助。
-
@Shahbaz-如果需要标准化,可靠的尺寸,请使用C99中专门为此目的添加的stdint.h。
-
@ChrisLutz,谢谢。我知道这一点。但是,我很好奇,因为我在这里已经听到很多有关这些的信息,所以我想弄清楚我的事实。再次感谢您的帮助:)
-
buffer = malloc(sizeof *buffer * N);易于编写,没有魔术数字,并且如果buffer的指针类型发生更改,则无需进行匹配/编辑。
没有必要。参见此处(例如)。
C标准将sizeof(char)定义为始终为1(字节)。请注意,由于sizeof返回多个字节,因此每个字节的位数无关紧要(实际上,无论如何都是8)。
摘自"新C标准。经济和文化评论"。
统计资料:sizeof的2.0%来自char,而1.5%-来自unsigned char。第1033页的1.2版本的书。
第1037页。
The number of bits in the representation of a character type is
irrelevant. By definition the number
of bytes in byte a character type is
one.
Coding Guidelines Developers sometimes
associate a byte as always containing
eight bits. On hosts where the
character type is 16 bits, this can
lead to the incorrect assumption that
applying sizeof to a character type
will return the value 2.
These issues are discussed elsewhere.
还有一点要记住的是,编译器静态知道sizeof(char)的值为1,并且还知道将数字乘以静态1意味着不需要进行乘法;编译器将对其进行优化。出于这些原因,不应考虑性能问题。
使用sizeof(char)使您的代码更具可读性和可移植性。
在x86上,我们都知道一个字符是1个字节。但是明确写下来可以使您的意图更清晰,这始终是一件好事。
另外,如果您的代码被放置在字符不是1个字节的其他平台上,该怎么办。如果一个字符只有4位怎么办?
同意,这不是必须的,但不会降低运行时间,在极少数情况下,您需要将代码移植到其他体系结构上,这是有回报的。
-
那就是我要问的。正式地,char是最小的可寻址内存块,不保证其为8位。问题在于,malloc和所有其他类似的东西是否按字符而不是8位字节工作。
-
好的,然后,是的,malloc的工作原理是字符,而不是字节。 malloc(1)将返回1个字符大小的内存块。
-
-1您的回答实际上是错误的。 sizeof(char)始终为1。如果char只有4位,则在该平台上4位是1字节,但是sizeof(char)被定义为1(字节),无论它有多少位。 CHAR_BITS宏解决了您讨论的问题。
-
UCHAR_MAX的最小可能值为255;最小值为255。因此,char不能为4位。