相关疑难解决方法(0)

如何在C中确定数组的大小?

如何在C中确定数组的大小?

也就是说,阵列可以容纳的元素数量是多少?

c memory arrays

907
推荐指数
17
解决办法
183万
查看次数

C中的静态断言

在C(而不是C++)中实现编译时静态断言的最佳方法是什么,特别强调GCC?

c gcc assert static-assert compile-time

79
推荐指数
4
解决办法
6万
查看次数

C的常见数组长度宏?

我已经看到了几个浮动数组长度的宏:

这个问题:

  • #define length(array) (sizeof(array)/sizeof(*(array)))
  • #define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))
  • #define SIZE(array, type) (sizeof(array) / (sizeof(type))

和Visual Studio的_countof:

#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
Run Code Online (Sandbox Code Playgroud)

我想知道的是:

  1. 那些使用array[0]和有*array什么区别?
  2. 为什么要首选?
  3. 它们在C++方面有区别吗?

c c++ arrays c-preprocessor

32
推荐指数
2
解决办法
3万
查看次数

在确定数组的大小时,括号会有所作为吗?

以下程序在gcc 4.8.2上两次打印相同的数字:

#include <stdio.h>

int main()
{
    char a[13];
    printf("sizeof a  is %zu\n", sizeof a );
    printf("sizeof(a) is %zu\n", sizeof(a));
}
Run Code Online (Sandbox Code Playgroud)

根据这篇reddit帖子,gcc在这方面并不符合标准,因为当数组到指针衰减没有发生时,括号表达式不在异常列表中.

这家伙是对的吗?这是相关的标准报价:

除非它是运算sizeof符或一元运算&符的操作数,或者是用于初始化字符数组数组的字符串文字,或者是用于初始化与元素类型兼容的数组的宽字符串文字,否则具有wchar_t的左值类型'array of type'被转换为一个表达式,其类型为'指向类型的指针',指向数组对象的初始成员而不是左值.

为了清楚起见,他认为(a)应该触发数组到指针的衰减,因为上面的列表中没有括号括起来(sizeof运算符,一元运算&符,字符串文字作为初始值).

c arrays sizeof parentheses language-lawyer

26
推荐指数
2
解决办法
993
查看次数

C中是否有一个标准函数可以返回数组的长度?

C中是否有一个标准函数可以返回数组的长度?

c arrays

24
推荐指数
3
解决办法
8654
查看次数

可靠地确定数组中的元素数量

每个C程序员都可以使用这个众所周知的宏来确定数组中元素的数量:

#define NUM_ELEMS(a) (sizeof(a)/sizeof 0[a])
Run Code Online (Sandbox Code Playgroud)

这是一个典型的用例:

int numbers[] = {2, 3, 5, 7, 11, 13, 17, 19};
printf("%lu\n", NUM_ELEMS(numbers));          // 8, as expected
Run Code Online (Sandbox Code Playgroud)

但是,没有什么能阻止程序员意外地传递指针而不是数组:

int * pointer = numbers;
printf("%lu\n", NUM_ELEMS(pointer));
Run Code Online (Sandbox Code Playgroud)

在我的系统上,这打印2,因为显然,指针是整数的两倍.我想过如何防止程序员错误地传递指针,我找到了一个解决方案:

#define NUM_ELEMS(a) (assert((void*)&(a) == (void*)(a)), (sizeof(a)/sizeof 0[a]))
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为指向数组的指针与指向其第一个元素的指针具有相同的值.如果改为传递指针,指针将与指向自身的指针进行比较,这几乎总是假的.(唯一的例外是递归的void指针,也就是指向自身的void指针.我可以忍受它.)

意外地传递指针而不是数组现在在运行时触发错误:

Assertion `(void*)&(pointer) == (void*)(pointer)' failed.
Run Code Online (Sandbox Code Playgroud)

太好了!现在我有几个问题:

  1. 我的用法是assert逗号表达式的左操作数有效标准C吗?也就是说,标准是否允许我assert用作表达式?对不起,如果这是一个愚蠢的问题:)

  2. 可以在编译时以某种方式完成检查吗?

  3. 我的C编译器认为这int b[NUM_ELEMS(a)];是一个VLA.有没有办法说服他呢?

  4. 我是第一个想到这个吗?如果是这样,我可以期待在天堂等待多少处女?:)

c arrays assert pointers sizeof

16
推荐指数
2
解决办法
2463
查看次数

C找到静态数组大小(防止错误)

查找静态数组的大小是一种常见操作.看:C找到静态数组大小 -sizeof(a) / sizeof((a)[0])

这可以包装成一个宏,例如:

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

但是它可能会意外地传入常规指针.

例如: void func(SomeArray **foo) { int i = ARRAY_SIZE(foo); }

虽然它的有效C,但往往最终成为一个逻辑错误.

它可以防止这种错误(利用每个处理器在零长度位域上失败).


#define ARRAY_SIZE(a) \
    ((sizeof(struct { int isnt_array : \
     ((const void *)&(a) == &(a)[0]); }) * 0) + \
     (sizeof(a) / sizeof(*(a))))
Run Code Online (Sandbox Code Playgroud)

我发现这个宏适用于GCC,但是对于间接引用的成员,它与Clang失败了.同error: expression is not an integer constant expression

例如:

  • char word[8]; int i = ARRAY_SIZE(word); 好.
  • struct Bar { word[8]; }
    void func(struct Bar *foo) { int i = ARRAY_SIZE(foo->word); …

c arrays c-preprocessor

14
推荐指数
1
解决办法
852
查看次数

有没有办法让countof()测试它的参数是否是一个数组?

用于计算数组中元素数量的经典宏是:

#define countof(a)  (sizeof(a) / sizeof(*(a)))
Run Code Online (Sandbox Code Playgroud)

这个问题是如果参数是指针而不是数组,它会无声地失败.是否有一种可移植的方法来确保此宏仅与实际数组一起使用,如果a不是数组则生成编译时错误?

编辑:我的问题似乎是这个问题的重复:拒绝指针的数组大小的宏

c arrays

11
推荐指数
1
解决办法
263
查看次数

是否有一种类型安全的方法来获取C中的数组元素?

在C中获取数组元素的通常方法是这样的:

#define COUNTOF(arr) (sizeof(arr) / sizeof(arr[0]))
Run Code Online (Sandbox Code Playgroud)

这导致了一个整数常量表达式,这也是一个非常好的加法.

问题是它不是类型安全的:int* i; COUNTOF(i); /* compiles :( */.在实践中,这应该很少出现,但为了正确起见,使这种类型安全是很好的.


在C++ 03中这很容易(在C++ 11中它更容易,留给读者练习):

template <typename T, std::size_t N>
char (&countof_detail(T (&)[N]))[N]; // not defined

#define COUNTOF(arr) (sizeof(countof_detail(arr)))
Run Code Online (Sandbox Code Playgroud)

这使用模板推导来获取N数组的大小,然后将其编码为类型的大小.

但是在C中我们没有得到那种语言功能.这是我做的小框架:

// if `condition` evaluates to 0, fails to compile; otherwise results in `value`
#define STATIC_ASSERT_EXPR(condition, value) \
        (sizeof(char[(condition) ? 1 : -1]), (value))

// usual type-unsafe method
#define COUNTOF_DETAIL(arr) (sizeof(arr) / sizeof(arr[0]))

// new method:
#define COUNTOF(arr)                            \
        STATIC_ASSERT_EXPR(/* ??? */,           \
                           COUNTOF_DETAIL(arr)) …
Run Code Online (Sandbox Code Playgroud)

c arrays c89 visual-c++

5
推荐指数
1
解决办法
389
查看次数

在编译时在c/c ++预处理宏中验证参数是ARRAY类型

有没有办法在ac宏的编译时验证参数是一个数组?

例如在这两个宏中:

#define CLEAN_ARRAY(arr) \
    do { \
        bzero(arr, sizeof(arr)); \
    } while (0)
Run Code Online (Sandbox Code Playgroud)

#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
Run Code Online (Sandbox Code Playgroud)

我尝试使用CTC(X),但无法找到任何方法来验证/警告是否arr不是一个数组.

c c++ gcc compiler-errors

4
推荐指数
3
解决办法
1717
查看次数

编译时断言以确定指针是否为数组

目前,我有以下代码块来进行安全字符串复制(它的工作原理):

#define STRCPY(dst, src) do { assert(((void*)(dst)) == ((void*) & (dst))); \
                              strlcpy(dst, src, sizeof(dst)); } while (0)
Run Code Online (Sandbox Code Playgroud)

所以它接受如下构造:

const char *src = "hello";
char dest[5];
STRCPY(dest, src); //hell
Run Code Online (Sandbox Code Playgroud)

并否认以下内容:

void (char *dst) {
    STRCPY(dst, "heaven"); //unknown size of dst
}
Run Code Online (Sandbox Code Playgroud)

问题是代码块会产生一个断言.有没有办法在编译时执行此检查?

所以我想在编译时遇到错误(比如创建一个负大小的数组),而不是在可能的情况下崩溃代码.

c assertion

4
推荐指数
1
解决办法
116
查看次数