我遇到了以下代码片段:
int a = 3;
printf("%d", sizeof(a)++);
Run Code Online (Sandbox Code Playgroud)
显然,这将使用 GCC 9.3.0 和 -std=c99 进行编译。虽然这不编译:
printf("%d", sizeof(3)++);
Run Code Online (Sandbox Code Playgroud)
GCC 打印错误
错误:左值需要作为增量操作数
在我编译第一个片段之前,我会预料到会出现这样的错误。
后缀 ++ 运算符的操作数应为 C99 标准的左值
后缀递增或递减运算符的操作数应具有限定或非限定的实数或指针类型,并且应为可修改的左值。
关于 sizeof Operator 的返回值(如预期):
sizeof 运算符产生其操作数的大小(以字节为单位),它可以是表达式或类型的括号名称。大小由操作数的类型决定。结果是一个整数。如果操作数的类型是变长数组类型,则对操作数求值;否则,不计算操作数并且结果是整数常量。
结果的值是实现定义的,其类型(无符号整数类型)是 size_t,定义在(和其他头文件)中。
sizeof(a)++编译怎么可能?这是未定义的行为还是我错过了什么?
我和其他许多人一样,使用智能指针在C++中包含不安全的内存操作,使用RAII等等,已经取得了巨大的成功.但是,当您具有析构函数,类,运算符重载等时,包装内存管理更容易实现.
对于使用原始C99编写的人,您可以在哪里指出(没有双关语)来帮助安全内存管理?
谢谢.
在C中,我想使用printf来显示指针,以便它们正确排列,我想用0填充它们.
我的猜测是,正确的方法是:
printf("%016p", ptr);
这有效,但是这个gcc抱怨以下消息:
warning: '0' flag used with ‘%p’ gnu_printf format
我已经谷歌搜索了一下,以下主题是关于同一主题,但并没有真正给出解决方案.
http://gcc.gnu.org/ml/gcc-bugs/2003-05/msg00484.html
阅读它,似乎gcc抱怨的原因是我建议的语法没有在C99中定义.但我似乎无法找到任何其他方式以标准批准的方式做同样的事情.
所以这是双重问题:
我意识到你可以只是#define一些整数,但为什么C在C99之前没有专用的布尔数据类型?
它在编程和逻辑中是如此常见,我不理解显式类型和符号的缺失.
应该使用C99中的数组索引的类型?它必须适用于LP32,ILP32,ILP64,LP64,LLP64等.它不一定是C89类型.
我找到了5位候选人:
size_tptrdiff_tintptr_t/uintptr_tint_fast*_t/uint_fast*_tint_least*_t/uint_least*_t有一个简单的代码可以更好地说明问题.什么是最好的类型i,并j在这两个特定的循环.如果有充分的理由,两种不同的类型也可以.
for (i=0; i<imax; i++) {
do_something(a[i]);
}
/* jmin can be less than 0 */
for (j=jmin; j<jmax; j++) {
do_something(a[j]);
}
Run Code Online (Sandbox Code Playgroud)
PS在问题的第一个版本中,我忘记了负面索引.
PPS我不打算编写C99编译器.但是编译器程序员的任何答案对我来说都是非常有价值的.
类似的问题:
当我尝试在Linux上编译它时gcc -std=c99,编译器抱怨不知道struct timespec.但是,如果我编译它没有-std=c99一切正常.
#include <time.h>
int main(void)
{
struct timespec asdf;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么会这样,有没有办法让它继续使用-std=c99?
我最近成为大学课程的助教,主要教授C. C90课程标准化,主要是由于广泛的编译器支持.具有以前Java经验的C新手的一个非常令人困惑的概念是变量声明和代码可能不在块内混合的规则(复合语句).
最终用C99解除了这个限制,但我想知道:有人知道它为什么会出现在那里吗?它是否简化了可变范围分析?它是否允许程序员指定堆栈应该为新变量增加哪些程序执行点?
我认为语言设计师如果完全没有任何目的就不会增加这样的限制.
据我了解,C规范说该类型int应该是目标平台上包含至少16位的最有效类型.
那不就是C99的定义int_fast16_t吗?
也许他们只是为了保持一致而把它放在那里,因为int_fastXX_t需要另一个?
更新
总结下面的讨论:
示例: x86-64上的MSVC具有32位int,即使在64位系统上也是如此.MS选择这样做是因为太多人认为int总是正好是32位,因此很多ABI会破坏.但是,如果x86-64上的64位值更快,则int_fast32_t可能是64位数.(我不认为实际情况如此,但它只是证明了这一点)
我不明白为什么这样做是错的:
const int n = 5;
int x[n] = { 1,1,3,4,5 };
Run Code Online (Sandbox Code Playgroud)
即使n已经是const值.
虽然这样做似乎适合GNU编译器:
const int n = 5;
int x[n]; /*without initialization*/
Run Code Online (Sandbox Code Playgroud)
我知道C99的VLA功能,我认为这与正在发生的事情有关,但我只需要澄清背景中发生的事情.
我在尝试制作常量正确的代码时偶然发现了一个小问题.
我本来想写一个函数,它接受一个const结构的指针,告诉编译器"请告诉我,如果我正在修改结构,因为我真的不想".
我突然想到编译器会允许我这样做:
struct A
{
char *ptrChar;
};
void f(const struct A *ptrA)
{
ptrA->ptrChar[0] = 'A'; // NOT DESIRED!!
}
Run Code Online (Sandbox Code Playgroud)
这是可以理解的,因为实际上const是指针本身,而不是它指向的类型.我想让编译器告诉我,我正在做一些我不想做的事情,但是,如果可能的话.
我使用gcc作为我的编译器.虽然我知道上面的代码应该是合法的,但我仍然检查它是否会发出警告,但没有任何结果.我的命令行是:
gcc -std=c99 -Wall -Wextra -pedantic test.c
Run Code Online (Sandbox Code Playgroud)
有可能解决这个问题吗?