当前位置: 首页>编程语言>正文

【C语言】C语言基础

C语言】C语言基础

important function

  • system("current os's commandline arguments in terminal") -------stdlib.h
  • scanf()
    • %*d,格式控制中星号可以屏蔽数字
    • %*[a-z],屏蔽区间
  • gets()
  • puts()
  • fgets()
  • fputs()
  • strlen() : 字符串的有效长度
  • strcpy(destination_arr,source_arr)
  • strncpy(destination_arr,source_arr,num)

Pointer

  • 指针变量是只存放内存地址值的变量,星号是用指针变量中存储的地址值去内存中访问该地址上存储的数据的操作符。星号加指针变量,变成一根指针:*p
int a = 1;
int* p = &a;
int b = *p;
  • 不是说p的值是1,而是p这个指针指向变量a的地址,即使a的值变了,但是指针还是指向a的地址,除非将p重新赋值,指向其他地方。
       /******************************************************************************************************
	*                                          POINTER                                                   *
	******************************************************************************************************/
	printf("***************************************************************************\n");
	printf("***************************       POINTER      ****************************\n");
	printf("***************************************************************************\n");
	/* void pointer, need to forced type conversion */
	/* NULL pointer: which point to '0x0000' memory addr,can't be referenced */
	/* Wild Pointer: which point to a unknown memory addr,it's dangerous */
	int* p;
	p = NULL;		// NULL pointer
//	printf("value of *p : %d\n", *p);	// ERROR

	p = 0x1111;		// Wild pointer
//	printf("value of *p : %d\n", *p);	// ERROR

	/* ================== const and pointer ================== */
	printf("================== const and pointer ==================\n");
	int a = 10;
	const int* p1 = &a;		// *p1 is const, but variable 'a' can be Modified, the pointer 'p1' can be Modified too

	/* so, here is a summary of pointer, the object pointer point to is only a address or cell space, not a variable or value,
	cause *p1 != a in logic. In Chinese, 指针,真的是一根只会指向一个方向,一个地址的,不会拐弯的针 ——→      */

	//	*p1 = 2;	// error, *p is not a modifiable value
	a = 2;		// fine 
	printf("value of *p1 is %d\n", *p1);
	printf("value of a is %d\n", a);
	int b = 20;
	p1 = &b;
	printf("after changed, value of *p1 is %d\n", *p1);
	printf("after changed, value of a is %d\n", a);

	int* const p2 = &b;		// p2 is const, but variable 'b' can be Modified, '*p2' can be Modified too
	int c = 30;
	b = 40;
	printf("value of *p2 is %d\n", *p2);
	printf("value of b is %d\n", b);
	//p2 = &c;		// error, p2 is const
	*p2 = c; b = 50;	// in here two statements,*p and b represent their respective way to find a same memory space, but *p2 != b
	printf("after changed, value of *p2 is %d\n", *p2);
	printf("after changed, value of b is %d\n", b);

	/* ================== array and pointer ================== */
	printf("================== array and pointer ==================\n");
	int array[] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("in the same situation: \n");
	int* arr_p;
	arr_p = array;
	printf("arr_p[0] is %d, array[0] is %d\n", arr_p[0], array[0]);
	printf("arr_p's address is : %d\n", arr_p);
	printf("(arr_p+1)'s address is : %d\n", arr_p+1); 
	printf("after arr_p+1, arr_p's address is : %d\n", arr_p);
	printf("(arr_p++)'s address is : %d\n", arr_p++);
	printf("after arr_p++, arr_p's address is : %d\n", arr_p);
	printf("(++arr_p)'s address is : %d\n", ++arr_p);
	printf("after ++arr_p, arr_p's address is : %d\n", arr_p);

	/* summary: although pointer, it still follow the regulation of (++/--), and while increment is 1,
	address which point to increase sizeof(type) */



	/* bubble sort in pointer */
	int* bubble_sort(int arr[]);
	int* parray = bubble_sort(arr);
	printf("parray sorted is [");
	for (int i = 0; i < length; i++)
	{
		printf(" %d", parray[i]);
		if (i < length - 1)
		{
			printf(",");
		}
	}
	printf("]\n");
	

	
	
	/**********************************************************************************************
	*                                    POINTER( hp win7)                                        *
	***********************************************************************************************/
	// define pointer
	int* p;
	int num = 1;
	p = &num;

	// Pointer memory footprint is different for x86 and X64 architectures, x86: 4 Byte, x64: 8 Byte
	printf("size of int-pointer is %d\n", sizeof(p));
	printf("size of char-pointer is %d\n", sizeof(char*));
	printf("size of short-pointer is %d\n", sizeof(short*));
	printf("size of long-pointer is %d\n", sizeof(long*));
	printf("size of float-pointer is %d\n", sizeof(float*));
	printf("size of double-pointer is %d\n", sizeof(double*));

	// *p and var point to a same object 
	int var = 100;
	p = &var;
	printf("p : %p\n", p);
	printf("*p : %d\n", *p);
	var = 200;
	printf("changed value of var, p : %p\n", p);
	printf("changed value of var, *p : %d\n", *p);
	*p = 400;
	printf("changed value of *p, address of var : %p\n", &var);
	printf("changed value of *p, var : %d\n", var);

	
	// implicit declaration
	printf("return value of fun() is %d\n",fun(49));


	//const
	int a = 1;
	int b = 2;
	int c = 3;
	int d = 4;
	const int* p1 = &a; //*p1 is  const,*p1指向的值不能直接被改变,但是可以间接被改变,通过修改指针变量存存放的地址
	printf("p1's value is %p\n", p1);
	printf("*p1 is ; %d\n", *p1);
	p1 = &b;
	printf("after change, p1's value is %p\n", p1);
	printf("after change, *p1 is ; %d\n", *p1);
	int* const p2 = &b;	//p2 is const
	//p2 = &c;	// error
	int const * p3 = &c;	//*p3 is const    ( const int* p <==> int const * p  )
	//*p3 = d;	//error
	p3 = &d;
	int e = *p3;
	printf("*p3 is %d\n", *p3);
	printf("e is %d\n", e);
	


	//typedef
	typedef int const* p4;		// pointer variable 
	p4* p5 = d;					// a pointer variable which point to a typedef pointer, store value of address is 0x0000 0004(cause d=4)
	printf("p5 is %d\n", p5);		// a pointer variable, which store an address
	printf("sizeof(p5) is %d\n", sizeof(p5));		// size of pointer variable
	//printf("*p5 is %d\n", *p5);		// ERROR, access memory address which stored in p5   < Read the access permissions conflict >
	printf("&p5 is %d\n", &p5);		// read an address value of this pointer variable p5

	p4* p6 = &d;				// a pointer variable which point to a typedef pointer, store value of address is d's address
	printf("p6 is %d\n", p6);		// a pointer variable, which store an address
	printf("sizeof(p6) is %d\n", sizeof(p6));		// size of pointer variable
	printf("*p6 is %d\n", *p6);		// access memory address which stored in p6(d's address)
	printf("&p6 is %d\n", &p6);		// read an address value of this pointer variable p6


	//**,***
	int f = 6;
	int* p7 = f;
	int** p8 = f;
	int** p9 = &f;
	int*** p10 = f;
	int*** p11 = &f;
	p4* p12 = &p6;
	int** p13 = &p6;
	printf("p7 is %d\n", p7);
	printf("p8 is %d\n", p8);
	printf("p9 is %d\n", p9);
	printf("p10 is %d\n", p10);
	printf("p11 is %d\n", p11);
	//printf("**p7 is %d\n", **p7);		// ERROR
	//printf("**p8 is %d\n", **p8);		// ERROR
	//printf("**p9 is %d\n", **p9);		// ERROR
	//printf("**p10 is %d\n", **p10);		// ERROR
	//printf("**p11 is %d\n", **p11);		// ERROR
	//printf("***p7 is %d\n", ***p7);		// ERROR
	//printf("***p8 is %d\n", ***p8);		// ERROR
	//printf("***p9 is %d\n", ***p9);		// ERROR
	//printf("***p10 is %d\n", ***p10);		// ERROR
	//printf("***p11 is %d\n", ***p11);		// ERROR
	printf("p12 is %d\n", p12);
	printf("*p12 is %d\n", *p12);
	printf("**p12 is %d\n", **p12);
	printf("p13 is %d\n", p13);
	printf("*p13 is %d\n", *p13);
	printf("**p13 is %d\n", **p13);
	/* summary : **,*** are same as a '*' when define a variable,没有**或者***的说法,*星号只是能
	用指针变量中存储的地址值去内存中访问该地址上存储的数据的操作符,也就是说它只能操作地址 */


	// arr != arr1, compare address
	int arr[] = { 1,2,3,4,5,6 };
	int arr1[] = { 1,2,3,4,5,6 };
	printf("arr is %p\n", arr);
	printf("arr1 is %p\n", arr1);
	

	// uninitialized
	/*int g;
	char h;
	short i;
	long j;
	float k;
	double l;*/
	/*int* m;
	char* n;
	double* o;*/
	/*printf("int's initial value is %d\n", g);
	printf("char's initial value is %c\n" ,h);
	printf("short's initial value is %d\n", i);
	printf("long's initial value is %d\n", j);
	printf("float's initial value is %f\n", k);
	printf("double's initial value is %lf\n", l);*/
	/*printf("int*'s initial value is %p\n", m);
	printf("char*'s initial value is %p\n", n);
	printf("double*'s initial value is %p\n", o);*/


	/* pointer array */
	//store array of type 'char*' 
	char* arr_char[] = { "C/C++","Java","Python","Golang" };
	// in this array,arr_char[i] is a address of element on index 'i',and it's first address of every string
	printf("arr_char[0]'s addr is %p\n", arr_char[0]);
	char* lang = "C/C++";
	char* lang1 = "C/C++";	// string is const like Java
	printf("lang is %d\n",lang);
	printf("lang is %p\n",lang);
	printf("lang1 is %d\n", lang1);
	printf("lang1 is %p\n", lang1);
	char* lang2 = '+';
	char* lang3 = '+';	// char is const from ASCII,decimal-addr is 43 in ASCII code
	printf("lang2 is %d\n", lang2);
	printf("lang2 is %p\n", lang2);
	printf("lang3 is %d\n", lang3);
	printf("lang3 is %p\n", lang3);
	int len = strlen(arr_char[0]);
	printf("length is %d\n", len);
	// so, it could find any char in this array by pointer value is being passed
	printf("this char is %c\n", *(arr_char[2] + 2));
	// 指针数组存储的是指向某种类型的指针的首地址,这里的arr_char[]就是
	int int_arry[] = { 1,2,3 };
	int* p_arry[] = { int_arry,4,5,6 };
	printf("pointer array's first address is :%p\n", p_arry);
	printf("p_arry[0] is %d\n", p_arry[0]);
	printf("*p_arry[0] is %d\n", *p_arry[0]);
	// summary: 指针数组中的元素表面上存的是非基本类型,其实和定义语句说的一样是存的指针,而值是该元素的首地址.如: int* p = int_array(&int_array[0](数组名就是首地址);
	// 又如:char lang[] = "C/C++";char* p = lang;
	

	/* 多级指针 */
	//二级指针指向一级指针
	//三级指针指向二级指针
	//....
	//三级指针可以用取地址符三次***,两次**,一次*
	//二级指针只有**,*
	//....





	char ccc[] = "jkl";
	char* p_ccc = ccc;
	printf("ccc is %d\n", ccc);
	printf("ccc[0] is %d\n", &ccc[0]);
	printf("*ccc is %d\n", *ccc);
	printf("*(&ccc[0]) is %d\n", *(&ccc[0]));
	printf("p_ccc is %d\n", p_ccc);
	printf("*p_ccc is %d\n", *p_ccc);
	printf("*p_ccc is %c\n", *p_ccc);

	/* 指针运算 */
	// char* arr_char[] = { "C/C++","Java","Python","Golang" };
	char** p_13 = arr_char;           
	/* 指向指针数组的指针应该是个二级指针,如果是一级指针,*p_13时就会出问题,因为普通的字符一级指针指向类似二维数组的指针数组(参考多级指针规则),
	所以这个指针只能一个字节的地方,不能完全识别整个指针数组 */
	char** p14 = &arr_char[1];	
	// 因为p_13和p14是指向的同一数组中的指针元素所指向的字符串的首地址!!!这非常重要,p_13和p14应该被定义为二级指针
	printf("p_13 is %p\n", p_13);
	printf("p14 is %p\n",p14);
	printf("&arr_char[0] is %p\n", &arr_char[0]);
	printf("&arr_char[0][0] is %p\n", &arr_char[0][0]);
	printf("&arr_char[1] is %d\n", &arr_char[1]);
	printf("arr_char is %p\n", arr_char);
	printf("*(&arr_char[0]) is %d\n", *(&arr_char[0]));
	printf("*(&arr_char[0]) is %c\n", *(&arr_char[0]));
	printf("*(&arr_char[0][0]) is %d\n", *(&arr_char[0][0]));
	printf("*(&arr_char[0][0]) is %c\n", *(&arr_char[0][0]));
	printf("*p_13 is %d\n",*p_13);	  
	printf("*p_13 is %s\n",*p_13);	
	printf("*p14 is %d\n", *p14);	
	printf("*p14 is %s\n", *p14);	
	printf("*arr_char is %p\n", *arr_char);
	printf("*arr_char is %c\n", *arr_char);
	printf("*(&arr_char[1]) is %d\n", *(&arr_char[1]));
	printf("p14 - p_13 is %d\n", p14 - p_13);
	printf("(int*)p14 - (int*)p_13 is %d\n", (int*)p14 - (int*)p_13);
	printf("(int*)p_13 is %d\n", (int*)p_13);
	printf("(int*)p14 is %d\n", (int*)p14);
	printf("*p14 - *p_13 is %d\n", *p14 - *p_13);
	printf("*(int*)p14 - *(int*)p_13 is %d\n", *(int*)p14 - *(int*)p_13);
	// 应该在了解数组名即是数组的首地址的同一时候,也要知道,数组名仅仅是“相当于”指针。而并不是真的是指针,数组名是仅仅是个常量(一个值为数组首元素地址的常量),所以
	//不能进行++或者–运算。而常量更是无法取地址的,而之所以有&a,事实上这里的a的意义早已经不是当初那个数组名了,它此时代表了整个数组。
	//因此,数组名,数组元素地址,指针的运算有各自不同的步长来增减

	int int_arr[] = {100,200,300};
	int* p15 = int_arr;
	int* p16 = &int_arr[1];
	printf("p15 is %d\n", p15);
	printf("int_arr is %d\n", int_arr);
	printf("&int_arr[0] is %d\n", &int_arr[0]);
	printf("p16 is %d\n", p16);
	printf("*int_arr is %d\n", *int_arr);
	printf("*(&int_arr[0]) is %d\n", *(&int_arr[0]));
	printf("*p15 is %d\n", *p15);
	printf("*p16 is %d\n", *p16);
	printf("p16 - p15 is %d\n", p16 - p15);
	printf("(int*)p16 - (int*)p15 is %d\n",(int*)p16 - (int*)p15);
	printf("*p16 - *p15 is %d\n", *p16 - *p15);
	printf("*(int*)p16 - *(int*)p15 is %d\n", *(int*)p16 - *(int*)p15);




	// "abc" "abcd" "a" "acgj"
	printf("abc's addr is %p\n", "abc");
	printf("abcd's addr is %p\n", "abcd");
	printf("a's addr is %p\n", "a");
	printf("a's addr is %p\n", 'a');
	printf("acgj's addr is %p\n", "acgj");

	// char* -> int*
	char chaxing = 10;
	int var1 = 10;
	printf("chaxing is %c\n", chaxing);
	printf("sizeof(chaxing) is %d\n", sizeof(chaxing));
	char* p_chaxing = &chaxing;
	char* p_var1 = &var1;
	*p_chaxing = 1000;
	printf("chaxing now is %d\n",chaxing);
	*(int*)p_var1 = 1000;
	printf("var1 now is %d\n", var1);

	
	/* pointer and parameters*/
	void exchange(int a, int b);
	int var2 = 10;
	int var3 = 20;
	printf("var2 , var3 : %d, %d\n", var2, var3);
	exchange(var2,var3);
	printf("after exchange, var2 , var3 : %d, %d\n", var2, var3); // summary: 值传递,变量并不会实际交换
	
	int* p_var2 = &var2;
	int* p_var3 = &var3;
	void exchange_addr(int* a, int* b);
	exchange_addr(p_var2, p_var3);
	printf("after exchange_addr, var2 , var3 : %d, %d\n", var2, var3);


	/* pointer as return */
	char* arr_vs_pointer();
	char* p_var4 = arr_vs_pointer();
	printf("p_var4's addr is %p\n", p_var4);	
	printf("p_var4 is %s\n", p_var4);		// 字符数组创建在栈区,随着return语句函数结束,它的生命周期也就完结了。所以找不到这个地址,跟上面一级指针指向指针数组类似,会产生乱码,加const也不行
	char* pointer_vs_arr();
	char* p_var5 = pointer_vs_arr();
	printf("p_var5's addr is %p\n", p_var5);
	printf("p_var5 is %s\n", p_var5);		// 定义为字符串常量,在程序运行时就创建在常量区,不能被修改,在函数外依然能被访问


      /* define and const */
	//printf("define: aaa is %s\n", aaa);		// error,这里相当于去内存中找地址为0x00000062的字符串,但是访问受限
	printf("define: aaa is %c\n", aaa);			// 字符 b 由98的ASCII码得
	printf("define: 2*aaa*3 is %d\n", 2 * aaa * 3);		//2*49+49*3 = 245
	const int bbb = 49 + 49;
	printf("const: 2*bbb*3 is %d\n", 2 * bbb * 3);		//2*98*3 = 588
	//summary: #define 声明的是常量,在预处理阶段进行,不会进行类型检查,不知道是整型函数字符型就原样不变的参与计算,参与表达式时才确定
	//			const  声明的是只读变量,在编译,运行阶段,会进行类型检查,可通过内存修改对应的值
	// ====  证明const不是常量 ====
	const int lens = 9;
	//int arr_l[lens]; // ERROR 表达式必须含有常量值





	return 0;
}
// implicit declaration
// return type and param are no-type,but complier could give a default type --- int.
fun(x)
{
	printf("param is %c\n",x);
	return x + 1;
}

void exchange(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
}

void exchange_addr(int* a, int* b)
{
	*a ^= *b;
	*b ^= *a;
	*a ^= *b;
}

char* arr_vs_pointer()
{
	char arr[] = "abcdefg";	// 字符数组创建在栈区,随着return语句函数结束,它的生命周期也就完结了。所以找不到这个地址,跟上面一级指针指向指针数组类似,会产生乱码,加const也不行
	return arr;
}

char* pointer_vs_arr()
{
	char* arr = "abcdefg";	// 定义为字符串常量,在程序运行时就创建在常量区,不能被修改,在函数外依然能被访问
	return arr;
}

Saturday, October 31, 2020

    Today, I have nothing to write, cause have not enough knowledge during study of day 
although watched many videos of C Language.
  Honestly,system(),strlen(),strcpy(),strncpy(),fgets(),fputs(),is not familiar to me in C.



Monday, November 2, 2020

    指针,真的是一根只会指向一个方向,一个地址的,不会拐弯的针 ——>
    const modify a object, this guy is const.



Tuesday, November 3, 2020

    Today,i still swimming in C-pointer knowledge.
What impressed me most was that define int* p1 = &a1,in this statement, 'a1' could be any variable,but int** p2 = &a2, 'a2' should be a pointer variable.
Among them, '*' can operate variable 'p1', but '*' can't operate '*p1', then '**p1' is ERROR.And 'p2' can be both operated by '*' and '**'.

https://www.xamrdz.com/lan/5c81967322.html

相关文章: