我想用指针参数初始化一个链表,如下所示:
/*
* Initialize a linked list using variadic arguments
* Returns the number of structures initialized
*/
int init_structures(struct structure *first, ...)
{
struct structure *s;
unsigned int count = 0;
va_list va;
va_start(va, first);
for (s = first; s != NULL; s = va_arg(va, (struct structure *))) {
if ((s = malloc(sizeof(struct structure))) == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
count++;
}
va_end(va);
return count;
}
Run Code Online (Sandbox Code Playgroud)
问题是,铛错误type name requires a specifier or qualifier的va_arg(va, (struct structure *)) …
再次,我们最喜欢的"i = i--"类问题.在C99,我们有:
6.5表达式#2:在前一个和下一个序列点之间,一个对象的存储值最多只能修改一次
70)这一段渲染!!未定义!! 语句表达式如
i = ++i + 1;
Run Code Online (Sandbox Code Playgroud)
但对于未完成的行为,可能存在从随机输出到"以文档化方式执行程序"的变体(c99 3.4.3)
那么,问题是:
gcc是否记录了 i = i ++,i = i--等行为的行为?
实际代码是
int main(){int i=2;i=i--;return i;}
Run Code Online (Sandbox Code Playgroud) 你可能认为我在编程时非常疯狂而且非常糟糕.其中一个可能是这种情况,但请阅读我的发现.
是的,我 #include <math.h>
完整代码可以在这里找到.(我试图让它符合ansi以使其在VS2010上编译,它通过关于混合代码和声明的错误,以及fminf()丢失.我很惊讶VS2010关注混合代码和声明以及默认警告级别.我回想起2008年不关心,但可能是错的.)
这是使用c89/-ansi标准时的gcc输出.注意函数的隐式声明.还有一些关于未使用参数的其他参数,但我们现在不关心它们.(需要签名才能使用GLUT注册回拨)
当我使用c89或ansi标准运行应用程序时,它会产生错误的输出,就像数学函数的行为不符合预期一样.
$ STANDARD=-std=c89 make -f Makefile.Unix
gcc -std=c89 -Wextra -Wall -pedantic -c -o file-util.o file-util.c -I/usr/X11R6/include
gcc -std=c89 -Wextra -Wall -pedantic -c -o gl-util.o gl-util.c -I/usr/X11R6/include
gcc -std=c89 -Wextra -Wall -pedantic -c -o meshes.o meshes.c -I/usr/X11R6/include
In file included from meshes.c:12:
vec-util.h: In function ‘vec_length’:
vec-util.h:10: warning: implicit declaration of function ‘sqrtf’
meshes.c: In function ‘calculate_flag_vertex’:
meshes.c:48: warning: implicit declaration of function ‘sinf’
meshes.c:50: warning: implicit declaration of function ‘cosf’
gcc -std=c89 -Wextra …Run Code Online (Sandbox Code Playgroud) 标准(最新版本:WG14/N1256)说(6.2.1§2):
函数原型是声明其参数类型的函数的声明.
在本声明的附近,我们还发现标识符声明由声明符或类型说明符组成的证据(§4):
每个其他标识符的范围由其声明的放置(在声明者或类型说明符中)确定.
因此,知道函数定义是否是函数原型似乎可以归结为知道函数定义是否是声明符.是吗 ?
我需要一个符合C标准的经过验证的答案.我并不真正关心通常的含义,或维基百科或你最喜欢的C书所说的.
以下是标准中的声明,使我认为函数定义确实可以是函数原型(§4):
如果声明标识符的声明符或类型说明符出现在函数原型的参数声明列表中(不是函数定义的一部分),...
我正在用C99编写一个库,并且库的某些部分可以从使用宏/内联函数中获益.内联函数更适合我的库.
但是,非常具体地说我不想在外部公开这些内联函数.
一切似乎都有效,但当我链接到库以创建可执行文件时,我得到错误:"未定义引用`na_impl_gfx__draw'"
我已经将问题复制到一个最小的测试用例,它完全符合我的要求:
lib.h:
void somefunc();
Run Code Online (Sandbox Code Playgroud)
lib.c:
#include <stdio.h>
#include "lib.h"
inline void someinline(char *value);
void somefunc() {
someinline("Hi!");
}
inline void someinline(char *value) {
printf("%s\n", value);
}
Run Code Online (Sandbox Code Playgroud)
main.c中:
#include "lib.h"
int main(int argc, char *argv[]) {
somefunc();
}
Run Code Online (Sandbox Code Playgroud)
现在我们编译:
doug@Wulf:~/test$ gcc -c -std=c99 lib.c
doug@Wulf:~/test$ gcc -c -std=c99 main.c
doug@Wulf:~/test$ gcc -std=c99 lib.o main.o
lib.o: In function `somefunc':
lib.c:(.text+0xe): undefined reference to `someinline'
lib.c:(.text+0x1a): undefined reference to `someinline'
lib.c:(.text+0x26): undefined reference to `someinline'
collect2: ld returned 1 exit …Run Code Online (Sandbox Code Playgroud) 我在C中实现了队列的实现.我的界面包含五个访问队列的简单函数:
#ifndef QUEUE_H
#define QUEUE_H
#include <stdbool.h>
#include <stddef.h>
struct queue {
struct cell* first;
struct cell* last;
};
typedef struct queue queue;
extern queue newQueue(void);
extern bool isEmpty(queue);
extern queue enqueue(queue,void*);
extern queue dequeue(queue);
extern void* front(queue);
extern void freeQueue(queue);
Run Code Online (Sandbox Code Playgroud)
由于其中两个(newQueue和isEmpty)是如此微不足道,我相信编译器可以用它们做很多好的优化,我决定为它们编写内联声明:
/* replacing the two lines
extern queue newQueue(void);
extern bool isEmpty(queue);
in the original header */
extern inline queue newQueue(void) {
queue q = { NULL, NULL };
return q;
}
extern inline bool …Run Code Online (Sandbox Code Playgroud) 我有以下代码.当我使用gnu extensions(-std=gnu99)编译它时,程序将在结束之前捕获5 SIGINT(我期望).在没有它的情况下编译(-std=c99)在第二个之后结束(并且只输出一行).
我错过了什么?
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
int int_stage = 0;
int got_signal = 0;
void sigint(int parameter)
{
(void)parameter;
got_signal = 1;
int_stage++;
}
int main()
{
signal(SIGINT,sigint);
while(1)
{
if (got_signal)
{
got_signal = 0;
puts("still alive");
if (int_stage >= 5) exit(1);
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud) 在atexit图书馆等大型项目中使用是否存在固有的危险?
如果是这样,那背后的技术性质atexit可能会导致大型项目出现问题?
假设我有一个i来自外部来源的变量:
int i = get_i();
Run Code Online (Sandbox Code Playgroud)
假设i是INT_MIN和的补码表示形式,是-i不确定的吗?
我一直在研究现有的C99代码库,该代码库在各处使用指向打包结构成员的指针。这会导致出现形式警告。
my_file.c:xxx:yy: error: taking address of packed member of 'struct some_packed_struct' may result in an unaligned pointer value [-Werror=address-of-packed-member]
Run Code Online (Sandbox Code Playgroud)
大多数时候,这些警告是在将指针传递给函数的结构成员时生成的。例如:
my_file.c:xxx:yy: error: taking address of packed member of 'struct some_packed_struct' may result in an unaligned pointer value [-Werror=address-of-packed-member]
Run Code Online (Sandbox Code Playgroud)
有很多解决此问题的方法。立即想到的是memcpy()将相同类型的堆栈分配变量的值传递给该堆栈变量。
int bar(const int *val)
{ ... }
struct {
int a;
char b;
int c;
} __attribute__((packed)) foo;
// &foo.c is not aligned
bar(&foo.c)
Run Code Online (Sandbox Code Playgroud)
在此过程中,它将产生许多样板代码,我希望避免引入。
目前,我一直在考虑使用以下形式的宏
#define ALIGN_VALUE_PTR(val) (&((const typeof(val)) { val }))
bar(ALIGN_VALUE_PTR(foo.c));
Run Code Online (Sandbox Code Playgroud)
这适用于标量类型。但是,可以预见的是,如果val为a struct,则将不起作用。 …