我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C语言中的0长度数组有什么用途

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C语言中的0长度数组有什么用途

本篇内容介绍了“C语言中的0长度数组有什么用途”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

零长度数组概念

众所周知, GNU/GCC 在标准的 C/C++ 基础上做了有实用性的扩展, 零长度数组(Arrays of Length Zero) 就是其中一个知名的扩展.

多数情况下, 其应用在变长数组中, 其定义如下:

struct Packet{    int state;    int len;    char cData[0]; //这里的0长结构体就为变长结构体提供了非常好的支持};

首先对 0长度数组, 也叫柔性数组 做一个解释 :

  • 用途 : 长度为0的数组的主要用途是为了满足需要变长度的结构体

  • 用法 : 在一个结构体的最后, 申明一个长度为0的数组, 就可以使得这个结构体是可变长的. 对于编译器来说, 此时长度为0的数组并不占用空间, 因为数组名本身不占空间, 它只是一个偏移量, 数组名这个符号本身代表了一个不可修改的地址常量

(注意 : 数组名永远都不会是指针!), 但对于这个数组的大小, 我们可以进行动态分配

注意 :如果结构体是通过calloc、malloc或 者new等动态分配方式生成,在不需要时要释放相应的空间。

优点 :比起在结构体中声明一个指针变量、再进行动态分 配的办法,这种方法效率要高。因为在访问数组内容时,不需要间接访问,避免了两次访存。

缺点 :在结构体中,数组为0的数组必须在最后声明,使 用上有一定限制。

对于编译器而言, 数组名仅仅是一个符号, 它不会占用任何空间, 它在结构体中, 只是代表了一个偏移量, 代表一个不可修改的地址常量!

0长度数组的用途

我们设想这样一个场景, 我们在网络通信过程中使用的数据缓冲区, 缓冲区包括一个len字段和data字段, 分别标识数据的长度和传输的数据, 我们常见的有几种设计思路:

  • 定长数据缓冲区, 设置一个足够大小 MAX_LENGTH 的数据缓冲区

  • 设置一个指向实际数据的指针, 每次使用时, 按照数据的长度动态的开辟数据缓冲区的空间

我们从实际场景中应用的设计来考虑他们的优劣. 主要考虑的有, 缓冲区空间的开辟, 释放和访问。

1、定长包(开辟空间, 释放, 访问):

比如我要发送 1024 字节的数据, 如果用定长包, 假设定长包的长度 MAX_LENGTH 为 2048, 就会浪费 1024 个字节的空间, 也会造成不必要的流量浪费:

数据结构定义:

//  定长缓冲区struct max_buffer{    int     len;    char    data[MAX_LENGTH];};

数据结构大小:考虑对齐, 那么数据结构的大小 >= sizeof(int) + sizeof(char) * MAX_LENGTH

由于考虑到数据的溢出, 变长数据包中的 data 数组长度一般会设置得足够长足以容纳最大的数据, 因此 max_buffer 中的 data 数组很多情况下都没有填满数据, 因此造成了浪费

数据包的构造:假如我们要发送 CURR_LENGTH = 1024 个字节, 我们如何构造这个数据包呢;一般来说, 我们会返回一个指向缓冲区数据结构 max_buffer 的指针:

    ///  开辟    if ((mbuffer = (struct max_buffer *)malloc(sizeof(struct max_buffer))) != NULL)    {        mbuffer->len = CURR_LENGTH;        memcpy(mbuffer->data, "Hello World", CURR_LENGTH);          printf("%d, %s\n", mbuffer->len, mbuffer->data);    }

访问:这段内存要分两部分使用;前部分 4 个字节 p->len, 作为包头(就是多出来的那部分),这个包头是用来描述紧接着包头后面的数据部分的长度,这里是 1024, 所以前四个字节赋值为 1024 (既然我们要构造不定长数据包,那么这个包到底有多长呢,因此,我们就必须通过一个变量来表明这个数据包的长度,这就是len的作用);而紧接其后的内存是真正的数据部分, 通过 p->data, 最后, 进行一个 memcpy() 内存拷贝, 把要发送的数据填入到这段内存当中

释放:那么当使用完毕释放数据的空间的时候, 直接释放就可以了

    /// 销毁    free(mbuffer);    mbuffer = NULL;

2、小结:

使用定长数组, 作为数据缓冲区, 为了避免造成缓冲区溢出, 数组的大小一般设为足够的空间 MAX_LENGTH, 而实际使用过程中, 达到 MAX_LENGTH 长度的数据很少, 那么多数情况下, 缓冲区的大部分空间都是浪费掉的

但是使用过程很简单, 数据空间的开辟和释放简单, 无需程序员考虑额外的操作

3、 指针数据包(开辟空间, 释放, 访问):

如果你将上面的长度为 MAX_LENGTH 的定长数组换为指针, 每次使用时动态的开辟 CURR_LENGTH 大小的空间, 那么就避免造成 MAX_LENGTH - CURR_LENGTH 空间的浪费, 只浪费了一个指针域的空间:

数据包定义:

struct point_buffer{    int     len;    char    *data;};

数据结构大小:考虑对齐, 那么数据结构的大小 >= sizeof(int) + sizeof(char *)

空间分配:但是也造成了使用在分配内存时,需采用两步

    // =====================    // 指针数组  占用-开辟-销毁    // =====================    ///  占用    printf("the length of struct test3:%d\n",sizeof(struct point_buffer));    ///  开辟    if ((pbuffer = (struct point_buffer *)malloc(sizeof(struct point_buffer))) != NULL)    {        pbuffer->len = CURR_LENGTH;        if ((pbuffer->data = (char *)malloc(sizeof(char) * CURR_LENGTH)) != NULL)        {            memcpy(pbuffer->data, "Hello World", CURR_LENGTH);              printf("%d, %s\n", pbuffer->len, pbuffer->data);        }    }

首先, 需为结构体分配一块内存空间;其次再为结构体中的成员变量分配内存空间。

这样两次分配的内存是不连续的, 需要分别对其进行管理. 当使用长度为的数组时, 则是采用一次分配的原则, 一次性将所需的内存全部分配给它。

释放:相反, 释放时也是一样的:

    /// 销毁    free(pbuffer->data);    free(pbuffer);    pbuffer = NULL;

小结:

  • 使用指针结果作为缓冲区, 只多使用了一个指针大小的空间, 无需使用 MAX_LENGTH 长度的数组, 不会造成空间的大量浪费

  • 但那是开辟空间时, 需要额外开辟数据域的空间, 施放时候也需要显示释放数据域的空间, 但是实际使用过程中, 往往在函数中开辟空间, 然后返回给使用者指向 struct point_buffer 的指针, 这时候我们并不能假定使用者了解我们开辟的细节, 并按照约定的操作释放空间, 因此使用起来多有不便, 甚至造成内存泄漏。

4、变长数据缓冲区(开辟空间, 释放, 访问)

定长数组使用方便, 但是却浪费空间, 指针形式只多使用了一个指针的空间, 不会造成大量空间分浪费, 但是使用起来需要多次分配, 多次释放, 那么有没有一种实现方式能够既不浪费空间, 又使用方便的呢?

GNU C 的0长度数组, 也叫变长数组, 柔性数组就是这样一个扩展. 对于0长数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等:

数据结构定义:

//  0长度数组struct zero_buffer{    int     len;    char    data[0];};

数据结构大小:这样的变长数组常用于网络通信中构造不定长数据包, 不会浪费空间浪费网络流量, 因为char data[0]; 只是个数组名, 是不占用存储空间的:

sizeof(struct zero_buffer) = sizeof(int)

开辟空间:那么我们使用的时候, 只需要开辟一次空间即可

///  开辟    if ((zbuffer = (struct zero_buffer *)malloc(sizeof(struct zero_buffer) + sizeof(char) * CURR_LENGTH)) != NULL)    {        zbuffer->len = CURR_LENGTH;        memcpy(zbuffer->data, "Hello World", CURR_LENGTH);          printf("%d, %s\n", zbuffer->len, zbuffer->data);    }

释放空间:释放空间也是一样的, 一次释放即可

    ///  销毁    free(zbuffer);    zbuffer = NULL;

总结:

// zero_length_array.c#include <stdio.h>#include <stdlib.h>  #define MAX_LENGTH      1024#define CURR_LENGTH      512 //  0长度数组struct zero_buffer{    int     len;    char    data[0];}__attribute((packed));  //  定长数组struct max_buffer{    int     len;    char    data[MAX_LENGTH];}__attribute((packed));  //  指针数组struct point_buffer{    int     len;    char    *data;}__attribute((packed)); int main(void){    struct zero_buffer  *zbuffer = NULL;    struct max_buffer   *mbuffer = NULL;    struct point_buffer *pbuffer = NULL;      // =====================    // 0长度数组  占用-开辟-销毁    // =====================    ///  占用    printf("the length of struct test1:%d\n",sizeof(struct zero_buffer));    ///  开辟    if ((zbuffer = (struct zero_buffer *)malloc(sizeof(struct zero_buffer) + sizeof(char) * CURR_LENGTH)) != NULL)    {        zbuffer->len = CURR_LENGTH;        memcpy(zbuffer->data, "Hello World", CURR_LENGTH);          printf("%d, %s\n", zbuffer->len, zbuffer->data);    }    ///  销毁    free(zbuffer);    zbuffer = NULL;      // =====================    // 定长数组  占用-开辟-销毁    // =====================    ///  占用    printf("the length of struct test2:%d\n",sizeof(struct max_buffer));    ///  开辟    if ((mbuffer = (struct max_buffer *)malloc(sizeof(struct max_buffer))) != NULL)    {        mbuffer->len = CURR_LENGTH;        memcpy(mbuffer->data, "Hello World", CURR_LENGTH);          printf("%d, %s\n", mbuffer->len, mbuffer->data);    }    /// 销毁    free(mbuffer);    mbuffer = NULL;     // =====================    // 指针数组  占用-开辟-销毁    // =====================    ///  占用    printf("the length of struct test3:%d\n",sizeof(struct point_buffer));    ///  开辟    if ((pbuffer = (struct point_buffer *)malloc(sizeof(struct point_buffer))) != NULL)    {        pbuffer->len = CURR_LENGTH;        if ((pbuffer->data = (char *)malloc(sizeof(char) * CURR_LENGTH)) != NULL)        {            memcpy(pbuffer->data, "Hello World", CURR_LENGTH);              printf("%d, %s\n", pbuffer->len, pbuffer->data);        }    }    /// 销毁    free(pbuffer->data);    free(pbuffer);    pbuffer = NULL;      return EXIT_SUCCESS;}

GNU Document中 变长数组的支持

参考:

17 Arrays of Length Zero
 
C Struct Hack &ndash; Structure with variable length array

在 C90 之前, 并不支持0长度的数组, 0长度数组是 GNU C 的一个扩展, 因此早期的编译器中是无法通过编译的;对于 GNU C 增加的扩展, GCC 提供了编译选项来明确的标识出他们:

  • -pedantic 选项,那么使用了扩展语法的地方将产生相应的警告信息

  • -Wall 使用它能够使GCC产生尽可能多的警告信息

  • -Werror, 它要求GCC将所有的警告当成错误进行处理

// 1.c#include <stdio.h>#include <stdlib.h>  int main(void){    char a[0];    printf("%ld", sizeof(a));    return EXIT_SUCCESS;}

我们来编译:

gcc 1.c -Wall   # 显示所有警告
#none warning and error
 
gcc 1.c -Wall -pedantic  # 对GNU C的扩展显示警告
1.c: In function &lsquo;main&rsquo;:
1.c:7: warning: ISO C forbids zero-size array &lsquo;a&rsquo;
 
 
gcc 1.c -Werror -Wall -pedantic # 显示所有警告同时GNU C的扩展显示警告, 将警告用error显示
cc1: warnings being treated as errors
1.c: In function &lsquo;main&rsquo;:
1.c:7: error: ISO C forbids zero-size array &lsquo;a&rsquo;

C语言中的0长度数组有什么用途

0长度数组其实就是灵活的运用的数组指向的是其后面的连续的内存空间:

struct buffer{    int     len;    char    data[0];};

在早期没引入0长度数组的时候, 大家是通过定长数组和指针的方式来解决的, 但是:

定长数组定义了一个足够大的缓冲区, 这样使用方便, 但是每次都造成空间的浪费

指针的方式, 要求程序员在释放空间是必须进行多次的free操作, 而我们在使用的过程中往往在函数中返回了指向缓冲区的指针, 我们并不能保证每个人都理解并遵从我们的释放方式

所以 GNU 就对其进行了0长度数组的扩展. 当使用data[0]的时候, 也就是0长度数组的时候,0长度数组作为数组名, 并不占用存储空间.

在C99之后,也加了类似的扩展,只不过用的是 char payload[]这种形式(所以如果你在编译的时候确实需要用到-pedantic参数,那么你可以将char payload[0]类型改成char payload[], 这样就可以编译通过了,当然你的编译器必须支持C99标准的,如果太古老的编译器,那可能不支持了)

// 2.c payload#include <stdio.h>#include <stdlib.h> struct payload{    int   len;    char  data[];}; int main(void){    struct payload pay;    printf("%ld", sizeof(pay));    return EXIT_SUCCESS;}

使用 -pedantic 编译后, 不出现警告, 说明这种语法是 C 标准的

gcc 2.c -pedantic -std=c99

C语言中的0长度数组有什么用途

所以结构体的末尾, 就是指向了其后面的内存数据。因此我们可以很好的将该类型的结构体作为数据报文的头格式,并且最后一个成员变量,也就刚好是数据内容了.

GNU手册还提供了另外两个结构体来说明,更容易看懂意思:

struct f1 {    int x;    int y[];} f1 = { 1, { 2, 3, 4 } }; struct f2 {    struct f1 f1;    int data[3];} f2 = { { 1 }, { 5, 6, 7 } };

我把f2里面的2,3,4改成了5,6,7以示区分。如果你把数据打出来。即如下的信息:

f1.x = 1
f1.y[0] = 2
f1.y[1] = 3
f1.y[2] = 4

也就是f1.y指向的是{2,3,4}这块内存中的数据。所以我们就可以轻易的得到,f2.f1.y指向的数据也就是正好f2.data的内容了。打印出来的数据:

f2.f1.x = 1
f2.f1.y[0] = 5
f2.f1.y[1] = 6
f2.f1.y[2] = 7

如果你不是很确认其是否占用空间. 你可以用sizeof来计算一下。就可以知道sizeof(struct f1)=4,也就是int y[]其实是不占用空间的。但是这个0长度的数组,必须放在结构体的末尾。如果你没有把它放在末尾的话。编译的时候,会有如下的错误:

main.c:37:9: error: flexible array member not at end of struct
     int y[];
         ^

到这边,你可能会有疑问,如果将struct f1中的int y[]替换成int *y,又会是如何?这就涉及到数组和指针的问题了. 有时候吧,这两个是一样的,有时候又有区别。

首先要说明的是,支持0长度数组的扩展,重点在数组,也就是不能用int *y指针来替换。sizeof的长度就不一样了。把struct f1改成这样:

struct f3 {    int x;    int *y;};

在32/64位下, int均是4个字节, sizeof(struct f1)=4,而sizeof(struct f3)=16

因为 int *y 是指针, 指针在64位下, 是64位的, sizeof(struct f3) = 16, 如果在32位环境的话, sizeof(struct f3) 则是 8 了, sizeof(struct f1) 不变. 所以 int *y 是不能替代 int y[] 的;

代码如下:

// 3.c#include <stdio.h>#include <stdlib.h>  struct f1 {    int x;    int y[];} f1 = { 1, { 2, 3, 4 } }; struct f2 {    struct f1 f1;    int data[3];} f2 = { { 1 }, { 5, 6, 7 } };  struct f3{    int x;    int *y;}; int main(void){    printf("sizeof(f1) = %d\n", sizeof(struct f1));    printf("sizeof(f2) = %d\n", sizeof(struct f2));    printf("szieof(f3) = %d\n\n", sizeof(struct f3));     printf("f1.x = %d\n", f1.x);    printf("f1.y[0] = %d\n", f1.y[0]);    printf("f1.y[1] = %d\n", f1.y[1]);    printf("f1.y[2] = %d\n", f1.y[2]);      printf("f2.f1.x = %d\n", f1.x);    printf("f2.f1.y[0] = %d\n", f2.f1.y[0]);    printf("f2.f1.y[1] = %d\n", f2.f1.y[1]);    printf("f2.f1.y[2] = %d\n", f2.f1.y[2]);     return EXIT_SUCCESS;}

C语言中的0长度数组有什么用途

0长度数组的其他特征

1、为什么0长度数组不占用存储空间:

0长度数组与指针实现有什么区别呢, 为什么0长度数组不占用存储空间呢?

其实本质上涉及到的是一个C语言里面的数组和指针的区别问题. char a[1]里面的a和char *b的b相同吗?

《 Programming Abstractions in C》(Roberts, E. S.,机械工业出版社,2004.6)82页里面说:

“arr is defined to be identical to &arr[0]”.

也就是说,char a[1]里面的a实际是一个常量,等于&a[0]。而char *b是有一个实实在在的指针变量b存在。所以,a=b是不允许的,而b=a是允许的。两种变量都支持下标式的访问,那么对于a[0]和b[0]本质上是否有区别?我们可以通过一个例子来说明。

参见如下两个程序 gdb_zero_length_array.c 和 gdb_zero_length_array.c:

//  gdb_zero_length_array.c#include <stdio.h>#include <stdlib.h> struct str{    int len;    char s[0];}; struct foo{    struct str *a;}; int main(void){    struct foo f = { NULL };     printf("sizeof(struct str) = %d\n", sizeof(struct str));     printf("before f.a->s.\n");    if(f.a->s)    {        printf("before printf f.a->s.\n");        printf(f.a->s);        printf("before printf f.a->s.\n");    }     return EXIT_SUCCESS;}

C语言中的0长度数组有什么用途

//  gdb_pzero_length_array.c#include <stdio.h>#include <stdlib.h> struct str{    int len;    char *s;}; struct foo{    struct str *a;}; int main(void){    struct foo f = { NULL };     printf("sizeof(struct str) = %d\n", sizeof(struct str));     printf("before f.a->s.\n");     if (f.a->s)    {        printf("before printf f.a->s.\n");        printf(f.a->s);        printf("before printf f.a->s.\n");    }     return EXIT_SUCCESS;}

C语言中的0长度数组有什么用途

可以看到这两个程序虽然都存在访问异常, 但是段错误的位置却不同

我们将两个程序编译成汇编, 然户 diff 查看他们的汇编代码有何不同

gcc -S gdb_zero_length_array.c -o gdb_test.s
gcc -S gdb_pzero_length_array.c -o gdb_ptest
diff gdb_test.s gdb_ptest.s
 
1c1
<   .file   "gdb_zero_length_array.c"
---
>   .file   "gdb_pzero_length_array.c"
23c23
<   movl    $4, %esi
---
>   movl    $16, %esi
30c30
<   addq    $4, %rax
---
>   movq    8(%rax), %rax
36c36
<   addq    $4, %rax
---
>   movq    8(%rax), %rax

#    printf("sizeof(struct str) = %d\n", sizeof(struct str));
23c23
<   movl    $4, %esi    #printf("sizeof(struct str) = %d\n", sizeof(struct str));
---
>   movl    $16, %esi  #printf("sizeof(struct str) = %d\n", sizeof(struct str));

从64位系统中, 汇编我们看出, 变长数组结构的大小为4, 而指针形式的结构大小为16:

f.a->s
30c30/36c36
<   addq    $4, %rax
---
>   movq    8(%rax), %rax

可以看到有:

  • 对于 char s[0] 来说, 汇编代码用了 addq 指令, addq $4, %rax

  • 对于 char*s 来说,汇编代码用了 movq 指令, movq 8(%rax), %rax

addq 对 %rax + sizeof(struct str), 即str结构的末尾即是char s[0]的地址, 这一步只是拿到了其地址, 而 movq 则是把地址里的内容放进去, 因此有时也被翻译为leap指令, 参见下一列子

从这里可以看到, 访问成员数组名其实得到的是数组的相对地址, 而访问成员指针其实是相对地址里的内容(这和访问其它非指针或数组的变量是一样的):

访问相对地址,程序不会crash,但是,访问一个非法的地址中的内容,程序就会crash。

// 4-1.c#include <stdio.h>#include <stdlib.h> int main(void){     char *a;    printf("%p\n", a);     return EXIT_SUCCESS;}
//4-2.c#include <stdio.h>#include <stdlib.h> int main(void){     char a[0];    printf("%p\n", a);     return EXIT_SUCCESS;}

对于 char a[0] 来说, 汇编代码用了 leal 指令, leal 16(%esp), %eax:

对于 char *a 来说,汇编代码用了 movl 指令, movl 28(%esp), %eax

2、地址优化:

// 5-1.c#include <stdio.h>#include <stdlib.h> int main(void){     char a[0];    printf("%p\n", a);     char b[0];    printf("%p\n", b);     return EXIT_SUCCESS;}

C语言中的0长度数组有什么用途

由于0长度数组是 GNU C 的扩展, 不被标准库任可, 那么一些巧妙编写的诡异代码, 其执行结果就是依赖于编译器和优化策略的实现的.

比如上面的代码, a和b的地址就会被编译器优化到一处, 因为a[0] 和 b[0] 对于程序来说是无法使用的, 这让我们想到了什么?

编译器对于相同字符串常量, 往往地址也是优化到一处, 减少空间占用:

//  5-2.c#include <stdio.h>#include <stdlib.h> int main(void){     const char *a = "Hello";    printf("%p\n", a);     const char *b = "Hello";    printf("%p\n", b);     const char c[] = "Hello";    printf("%p\n", c);     return EXIT_SUCCESS;}

C语言中的0长度数组有什么用途

“C语言中的0长度数组有什么用途”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C语言中的0长度数组有什么用途

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C语言中的0长度数组有什么用途

本篇内容介绍了“C语言中的0长度数组有什么用途”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!零长度数组概念众所周知, GNU/GCC 在标准
2023-07-05

一文带你了解C语言中的0长度数组(可变数组/柔性数组)

众所周知, GNU/GCC 在标准的 C/C++ 基础上做了有实用性的扩展, 零长度数组(Arrays of Length Zero) 就是其中一个知名的扩展,本文就来聊聊零长度数组的相关知识吧
2023-03-19

c语言变长数组的用法是什么

C语言中的变长数组(Variable Length Arrays,VLA)是指在定义数组时,可以使用变量作为数组的长度。变长数组的长度可以在运行时进行指定,而不是在编译时确定。变长数组的定义方式与普通数组类似,只是在定义数组时使用变量来指
c语言变长数组的用法是什么
2024-03-13

c语言怎么计算字符数组的长度

在C语言中,可以使用库函数strlen来计算字符数组的长度。strlen函数的原型为:```csize_t strlen(const char *str);```其中,参数str是要计算长度的字符数组或字符串。函数会返回一个size_t类型
2023-10-09

C语言中的数组和指针有什么作用

本文小编为大家详细介绍“C语言中的数组和指针有什么作用”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言中的数组和指针有什么作用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。指针相信大家对下面的代码不陌生:i
2023-06-16

c语言变长数组定义的方法是什么

在C语言中,变长数组(Variable Length Arrays,VLA)可以通过指定数组大小为变量来定义。变长数组的大小在编译时确定,可以根据程序运行时的需要动态调整大小。变长数组的定义方法如下所示:int main() {int
c语言变长数组定义的方法是什么
2024-03-13

c语言数组初始化为0的方法是什么

C语言数组初始化为0的方法有以下几种:1. 使用循环将每个元素赋值为0:```cint arr[10];for(int i = 0; i arr[i] = 0;}```2. 使用静态初始化方式将所有元素赋值为0:```cint arr[10
2023-10-08

c语言变长数组初始化的方法是什么

在C语言中,变长数组是指数组的大小在编译时不确定,而是在运行时确定的数组。变长数组的初始化方法与普通数组相同,可以使用花括号{}来初始化数组的元素。例如:int size = 5;int arr[size] = {1, 2, 3, 4,
c语言变长数组初始化的方法是什么
2024-03-13

C语言作用域和数组有什么作用

今天小编给大家分享一下C语言作用域和数组有什么作用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。作用域  任何一种编程中,作
2023-06-17

C语言中memset函数有什么用

这篇文章主要介绍C语言中memset函数有什么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!memset作用:内存设置函数原型:void *memset( void *dest, int c, size_t cou
2023-06-03

C语言中memcmp函数有什么用

这篇文章主要介绍了C语言中memcmp函数有什么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。memcmp作用:内存比较函数原型:int memcmp( const voi
2023-06-03

C语言中memmove函数有什么用

这篇文章将为大家详细讲解有关C语言中memmove函数有什么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。memmove作用:内存拷贝(可拷贝重叠内存)原型:void *memmove( void *d
2023-06-03

C语言中memcpy函数有什么用

这篇文章主要为大家展示了“C语言中memcpy函数有什么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C语言中memcpy函数有什么用”这篇文章吧。memcpy作用:内存拷贝函数原型:void
2023-06-03

c语言中的float有什么用

c语言中的floatfloat是什么?float是C语言中表示浮点数的数据类型。浮点数是带有小数部分的数字,用于表示非常大或非常小的数值或具有小数位精确度的数据。float的用途float数据类型通常用于以下情况:表示小数部分:例如,表
c语言中的float有什么用
2024-05-10

C语言中数组和指针的作用是什么

这篇文章将为大家详细讲解有关C语言中数组和指针的作用是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。指针相信大家对下面的代码不陌生:int i=2;
2023-06-17

C语言中%*s的*有什么作用

这篇“C语言中%*s的*有什么作用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C语言中%*s的*有什么作用”文章吧。取决于
2023-06-27

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录