array variable used in printf function

简介:
在C中, array变量和指针极其相似.

指针加减运算, 首先需要知道指针类型, 类型占用的字节数, 如int *的指针, 加1 则表示地址加4字节(假设32位的机器int占4字节);
如果是char * 的指针, 指针变量加1则表示地址加1字节(char 占1个字节).

例子1 : 
#include <stdio.h>
#include <stdlib.h>

int main() {
char a[10] = "abcdefg";
printf("a[0]:%i\n",a[0]);
printf("a[0]:%c\n",a[0]);
printf("a:%s\n",&a[0]);
printf("a:%s\n",a);
printf("a<<1:%s\n",&a[1]);
printf("addr(a):%p\n",a);
printf("addr(a[0]):%p\n",&a[0]);
return 0;
}


gcc -O3 -Wall -Wextra -Werror -g ./l.c -o l && ./l
a[0]:97
a[0]:a
a:abcdefg
a:abcdefg
a<<1:bcdefg
addr(a):0x7fff7f92b310
addr(a[0]):0x7fff7f92b310

从地址上看array变量应该在stack里面, 属于高位地址. 因为array定义后无法改变它指向的地址. 用于指向array创建时分配的空间的首地址.
array variable used in printf function - 德哥@Digoal - The Heart,The World.
 

例子2 : 
#include <stdio.h>
#include <stdlib.h>

int main() {
char *a = "abcdefg";
printf("a[0]:%i\n",a[0]);
printf("a[0]:%c\n",a[0]);
printf("a:%s\n",&a[0]);
printf("a:%s\n",a);
printf("a<<1:%s\n",&a[1]);
printf("addr(a):%p\n",a);
printf("addr(a[0]):%p\n",&a[0]);
return 0;
}


gcc -O3 -Wall -Wextra -Werror -g ./l.c -o l && ./l
a[0]:97
a[0]:a
a:abcdefg
a:abcdefg
a<<1:bcdefg
addr(a):0x40063a
addr(a[0]):0x40063a

从地址上看指针变量应该在constants里面, 属于低位地址. 因为指针指向的是 "abcdefg"这个常量的首地址, 字符串是放在内存的constants区域的 .
array variable used in printf function - 德哥@Digoal - The Heart,The World.
 
constants区域不能改变. 

另外指针加减算法得到的结果还是指针, 但是如果要得到结果指向的内容可以使用*, 或者[]. 如下 : 
array variable used in printf function - 德哥@Digoal - The Heart,The World.
 

printf 函数, 在打印%s时, 对应的参数必须是char *. 在打印%c 和 %i 时对应的参数必须是int. 打印%p时对应的参数必须是指针.


另外需要注意的几点 : 
1. 调用函数时, 传递的是值, 而不是传入的变量本身, 所以如果要修改传入的变量的值, 使用指针传递是比较好的方法, 因为拷贝指针的值指向的是想修改的变量地址.
2. 通过指针修改变量的值, 可使用* 或者[]. 如上图.
例如 : 
#include <stdio.h>
#include <stdlib.h>

char a[] = "abc";

void exchange1(char * i) {
  char x;
  x = i[0];
  i[0] = i[2];
  i[2] = x;
}

void exchange2(char * i) {
  char x;
  x = *i;
  *i = *(i+2);
  *(i+2) = x;
}

int main() {
  printf("old a:%s\n", a);
  exchange1(a);
  printf("new1 a:%s\n", a);
  exchange2(a);
  printf("new2 a:%s\n", a);
  return 0;
}


gcc -O3 -Wall -Wextra -Werror -g ./l.c -o l && ./l
old a:abc
new1 a:cba
new2 a:abc

3. 由于char * a = "ABC" 这种方式定义的指针, 字符串是存储在constants区域的, 无法修改. 所以一般这种定义可以改为const char * a = "ABC"/
 那么在代码中如果出现a[0]="O"; 这种语句时编译器会报错. 更容易理解.
从内存地址可以看出加了const和未加const定义的变量, 他们存放的内存区域是不一样的.
#include <stdio.h>
#include <stdlib.h>

const char a[] = "abc";
const char b[] = "abc";
char c[] = "abc";
char d[] = "abc";
char *e = "abc";
char *f = "abc";

int main() {
  printf("addr a:%p\n", a);
  printf("addr b:%p\n", b);
  printf("addr c:%p\n", c);
  printf("addr d:%p\n", d);
  printf("addr e:%p\n", e);
  printf("addr f:%p\n", f);
  return 0;
}


gcc -O3 -Wall -Wextra -Werror -g ./l.c -o l && ./l
addr a:0x40065e
addr b:0x400662
addr c:0x600910
addr d:0x600914
addr e:0x40065a
addr f:0x40065a

同时你会发现constant "abc". 只放了一份. e和f指向同一地址.

4. Q: I still don’t understand why an array variable isn’t stored in memory. If it exists, surely it lives somewhere?

A: When the program is compiled, all the references to array variables are replaced with the addresses of the array. 
So the truth is that the array variable won’t exist in the final executable. That’s OK because the array variable will never be needed to point anywhere else.

Q: If I set a new array to a string literal, will the program really copy the contents each time?

A: It’s down to the compiler. The final machine code will either copy the bytes of the string literal to the array, or else the program will simply set the values of each character every time it reaches the declaration.

Q: You keep saying “declaration.” What does that mean?

A: A declaration is a piece of code that declares that something (a variable, a function) exists. A definition is a piece of code that says what something is. If you declare a variable and set it to a value (e.g., int x = 4;), then the code is both a declaration and a definition.
目录
相关文章
|
安全 C语言
警告 1 warning C4996: ‘scanf‘: This function or variable may be unsafe.
警告 1 warning C4996: ‘scanf‘: This function or variable may be unsafe.
|
C++
warning C4996 sprintf This function or variable may be unsafe
warning C4996 sprintf This function or variable may be unsafe
87 0
|
计算机视觉
opencv出错:error: (-213:The function/feature is not implemented) Unknown/unsupported array type
opencv出错:error: (-213:The function/feature is not implemented) Unknown/unsupported array type
477 0
|
安全
VS2019 error C4996: ‘scanf‘: This function or variable may be unsafe 错误
VS2019 error C4996: ‘scanf‘: This function or variable may be unsafe 错误
337 0
VS2019 error C4996: ‘scanf‘: This function or variable may be unsafe 错误
组件是默认值报错:Props with type Object/Array must use a factory function to return the default value
组件是默认值报错:Props with type Object/Array must use a factory function to return the default value
358 0
组件是默认值报错:Props with type Object/Array must use a factory function to return the default value
VS2017报错:严重性 代码 说明 项目 文件 行 禁止显示状态 错误 C4996 'strcpy': This function or variable may be unsafe. Consid
VS2017报错:严重性 代码 说明 项目 文件 行 禁止显示状态 错误 C4996 'strcpy': This function or variable may be unsafe. Consid
694 0
|
存储 JavaScript 前端开发
【JavaScript框架封装】使用Prototype给Array,String,Function对象的方法扩充
版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81055991 ...
1143 0