不允许使用其地址访问C中的位字段的原因是什么,是因为它可能不是一个非系统字对齐的地址..? 或者因为在一个字节内得到位的地址没有意义……?(因为这种类型的指针运算会很尴尬吗?)
我有一个简单的任务,教授希望我们这样做。 基本上从文本文件中提取一些数字并加载到链表中。 我不想深入了解细节,但我有一个基本问题。 他为我们提供了这样的function: INTLIST* init_intlist( int n ) { INTLIST *lst; lst = (INTLIST *)malloc(sizeof(INTLIST)); lst->datum = n; lst->next = NULL; return lst; } 此函数用于使用第一个元素初始化链接列表。 然后他要我们用这个签名定义一个函数: int insert_intlist( INTLIST *lst, int n ) 所以我假设他只是想让我们添加到链表中,所以我尝试了这个: int insert_intlist( INTLIST *lst, int n ) { INTLIST* lstTemp; lstTemp = (INTLIST *)malloc(sizeof(INTLIST)); lstTemp->datum = n; lstTemp->next = lst; […]
const struct sockaddr FAR* name,
我遇到了一段代码(使用XLC8和MSFT9编译器),包含一个带有C链接和引用参数定义的函数的C ++文件。 这让我很烦,因为引用只是C ++。 有问题的函数是从C代码调用的,其中它被声明为将指针参数取代为相同类型而不是引用参数。 简化示例 : C ++文件 : extern “C” void f(int &i) { i++; } C档案 : void f(int *); int main() { int a = 2; f(&a); printf(“%d\n”, a); /* Prints 3 */ } 现在,街上的一句话就是大多数C ++编译器,它们都像指针一样实现引用。 是这样的,只是纯粹的运气,这个代码工作的原因,或者它在C ++规范中的某处说,当你用引用参数和C链接定义一个函数时结果是什么? 我无法找到任何相关信息。
当我编译这样的东西 double da[ 3 ] = { 2., 3., 4. }; double (* pda)[ 3 ] = &da; double const (* cpda)[ 3 ] = pda; // gcc: warning; MSVC: ok gcc警告我 warning: initialization from incompatible pointer type [enabled by default] 问题:这项任务有什么问题? 是的,从技术上讲,这些是不同的类型,但我没有看到任何危险, double const (*)[ 3 ]看起来比double (*)[ 3 ]更安全。 我做了一些测试,结果让我更加困惑: 1)MSVC非常满意double const (* […]
我在一个struct中有一个函数指针,它在运行时动态设置为我代码中不同位置的另一个函数的地址。 它在我的头文件中定义如下: void *(*run)(); 在编译期间,我收到以下关于此的警告: warning: function declaration isn’t a prototype 这个警告是良性的,因为指针在我的代码中的许多地方用来调用它指向的函数,一切正常。 但是,我真的想要保持警告。 如果我改成它: void *(*run)(void); 我使用它时会遇到编译错误,因为使用指针的各种函数具有不同数量的参数,并且在括号内表示void告诉编译器它不接受任何参数。 我不能使用va_list或类似的任何东西,因为这只是指向另一个函数的指针,我使用单个指针,因为它保持代码干净和简单。 我可以通过将此添加到我的编译器标志来使警告静音: -Wno-strict-prototypes 但是如果我能避免它,我宁愿不用标志来禁用编译器警告。 所以我的问题是: 我如何在代码中注释这个函数指针,使编译器满意它接受任意数量的任何类型的参数这一事实? 代码完美无缺。 我只想让警告消失。
我有一个关于指针差异和结果类型的问题, ptrdiff_t 。 C99§6.5.6(9)说: 当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素的元素; 结果是两个数组元素的下标的差异。 结果的大小是实现定义的,其类型(有符号整数类型)是标头中定义的ptrdiff_t 。 如果结果在该类型的对象中无法表示,则行为未定义。 换句话说,如果表达式P和Q分别指向数组对象的第i和第j个元素,则表达式(P) – (Q)具有值i-j,条件是该值适合于ptrdiff_t类型的对象。 §7.18.3(2)要求ptrdiff_t的范围至少为[-65535,+ 65535] 我感兴趣的是如果结果太大则未定义的行为。 我无法在标准中找到任何保证至少与size_t的签名版本或类似内容相同的范围。 所以,现在我的问题是:一致的实现是否可以使ptrdiff_t成为带符号的16位类型但size_t 64位? [编辑:正如Guntram Blohm所指出的那样,16位有符号最多会产生32767,所以我的例子显然不符合]据我所知,我不能在严格符合代码甚至超过65535个元素的数组上做任何指针减法如果实现支持比这大得多的对象。 此外,该程序甚至可能崩溃。 理由(V5.10)§6.5.6说: 重要的是要对这种类型[ ptrdiff_t ]进行签名,以便在处理同一数组中的指针时获得正确的代数排序。 但是,指针差异的大小可以与可以声明的最大对象的大小一样大; 由于这是一个无符号类型,两个指针之间的差异可能会导致某些实现溢出。 这可以解释为什么不需要指定每个指针差异(对同一个数组的元素),但是它没有解释为什么对PTRDIFF_MAX没有限制至少为SIZE_MAX/2 (具有整数除法) 。 为了说明,假设T是任何对象类型,并且n是在编译时未知的size_t对象。 我想为T n对象分配空间,我想用指定范围内的地址进行指针减法。 size_t half = sizeof(T)>1 ? 1 : 2; // (*) if( SIZE_MAX/half/sizeof(T)<n ) /* do some error handling */; size_t size = […]
对于该计划: #include int main(void) { int (*a)[2]; int b[5]; printf(“sizeof(int) : %zu\n”, sizeof(int)); printf(“sizeof(int*) : %zu\n”, sizeof(int*)); printf(“sizeof(b) : %zu\n”,sizeof(b)); printf(“sizeof((int*)b) : %zu\n”,sizeof((int*)b)); printf(“sizeof(&b[0]) : %zu\n”,sizeof(&b[0])); printf(“sizeof(a) : %zu\n”,sizeof(a)); printf(“sizeof(a[0]) : %zu\n”,sizeof(a[0])); printf(“sizeof(a[1]) : %zu\n”,sizeof(a[1])); return 0; } 输出是: sizeof(int) : 4 -> Fact 1 sizeof(int*) : 8 -> Fact 2 sizeof(b) : 20 -> […]
我试着运行这段代码, int *p; float q; q = 6.6; p = &q; 虽然这将是一个警告,但我认为&q和p具有相同的大小,所以p可以具有q的地址。 但是当我打印&q和p我得到不同的输出。 这是我的输出 *p = 6.600000 q = 0.000000, p = 0x40d33333, &q = 0x7fffe2fa3c8c 我错过了什么? 当指针和变量类型相同时, p和&q相同。 我的完整代码是 #include void main() { int *p; float q; q = 6.6; p = &q; printf(“*p = %f \nq = %f, p = %p, &q = […]
linux内核(和其他地方)中常用的宏是container_of ,它(基本上)定义如下: #define container_of(ptr, type, member) (((type) *)((char *)(ptr) – offsetof((type), (member)))) 这基本上允许恢复“父”结构给定指向其中一个成员的指针: struct foo { char ch; int bar; }; … struct foo f = … int *ptr = &f.bar; // ‘ptr’ points to the ‘bar’ member of ‘struct foo’ inside ‘f’ struct foo *g = container_of(ptr, struct foo, bar); // now, ‘g’ should […]