初始c笔记bing

Posted 鸟随二月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初始c笔记bing相关的知识,希望对你有一定的参考价值。

类型字节

char 1
short 2
int 16位电脑 2 32/64位 4
long 4 linux 8
long long 8
float 4
double 8
long double 8

c上机过程

(程序)编辑、(源程序,.c)编译、(目标程序,.obj)连接、(可执行程序,*.exe)运行、结果

转义字符

\\ddd 1-3位8进制 如:”\\101“是 101
\\xdd 2位 16进制 如:"\\x41" 是41
“>>” 左补最高符号位
“<<” 右补0

特殊程序

int d=(10,20);//d=20
extern void fun();//static 修饰只能再当前.c使用

标识符常量预编译


指针

在32位中指针4字节,64位中指针8字节

switch

c中 switch(a) a是整型,char

void *memset(void *str, int c, size_t n)

EOF对应的命令行是ctrl+z

预防头文件重复编译

数组

整型提升

char a=1,b=1,c; 
c=a+b;

a,b先提升整形后(最高位是几补几),运算后再转化成char。即(char 和short使用前先转化成整型),这个过程叫做整型提升

sizeof()

返回的是无符号整型

指针

void类型的指针不可±操作

避免野指针

  1. 指针初始化
  2. 小心指针越界
  3. 指针指向空间释放即使置NULL
  4. 避免返回局部变量的地址
  5. 指针使用之前检查有效性

指针可以与数组之后的元素比较,不可以于之前的元素比较

int a[10]=1,2,3,4;
//a和&a[0]代表首元素地址,&a代表整个数组地址

二级指针

指针与函数

对于一个函数而言,当形参是指针变量时,对应的实参可以是指针变量,也可以是存储单元地址,此时的指针变量也遵守单向传递的原则(实参向形参传递)

指针函数

函数返回值是指针的函数。

函数指针

指向函数的指针变量
作用:通过函数指针数组,实现转移表的效果;实现函数回调效果

例子:

# include <stdio.h>
int Max(int, int);  
int main(void)

    int(*p)(int, int);  //定义一个函数指针
    int a, b, c;
    printf("%d",Max); //或者 &Max 函数地址 
    p = Max;  //把函数Max赋给指针变量p, 使p指向Max函数
    printf("please enter a and b:");
    scanf("%d%d", &a, &b);
    c = (*p)(a, b);  
    //通过函数指针调用Max函数,可以化简为 p(a,b)
    printf("a = %d\\nb = %d\\nmax = %d\\n", a, b, c);
    return 0;

int Max(int x, int y)  

    int z;
    if (x > y)
    
        z = x;
    
    else
    
        z = y;
    
    return z;

把0号地址对应的内存,当成一个函数指针来执行~

指针数组

存放指针的数组

int *a[3];

数组指针

指向数组的指针

数组与指针

  1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
  2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
  3. 除此之外所有的数组名都表示首元素的地址。

指针与字符串

char *a="123";
printf("%s",a);

回调函数

#include <stdio.h>
//qosrt函数的使用者得实现一个比较函数
int int_cmp(const void * p1, const void * p2) 
  return (*( int *)p1 - *(int *) p2);

int main()

    int arr[] =  1, 3, 5, 7, 9, 2, 4, 6, 8, 0 ;
    int i = 0;
    
    qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
    for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
   
       printf( "%d ", arr[i]);
   
    printf("\\n");
    return 0; 

使用回调函数,模拟实现qsort(采用冒泡的方式)。

 #include<stdio.h>
 int int_cmp(const void * p1, const void * p2) 
 return (*( int *)p1 - *(int *) p2);

void _swap(void *p1, void * p2, int size) 
 int i = 0;
 for (i = 0; i< size; i++)
 
char tmp = *((char *)p1 + i);
 *(( char *)p1 + i) = *((char *) p2 + i);
  *(( char *)p2 + i) = tmp;
  

void bubble(void *base, int count , int size, int(*cmp )(const  void *,const  void *))

 int i = 0;
int j = 0;
for (i = 0; i< count - 1; i++)
  
 for (j = 0; j<count-i-1; j++)
  
if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0)
 
  _swap(( char *)base + j*size, (char *)base + (j + 1)*size, size);
 
  
  

int main()

int arr[] =  1, 3, 5, 7, 9, 2, 4, 6, 8, 0 ;
 //char *arr[] = "aaaa","dddd","cccc","bbbb";
 int i = 0;
 bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
 for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
 
 printf( "%d ", arr[i]);
  
 printf("\\n");
 return 0; 

指针面试题



strlen()函数形参时 * char类型的
以下是未定义应用(没有以/0结束),strlen是针对字符串使用的,










%p 打印地址


代码

// 第八题
	char* c[] =  "ENTER","NEW","POINT","FIRST" ;
	char** cp[] =  c + 3,c + 2,c + 1,c ;
	char*** cpp = cp;
	printf("%s\\n", **++cpp);
	printf("%s\\n", *-- * ++cpp + 3);
	printf("%s\\n", *cpp[-2] + 3);
	printf("%s\\n", cpp[-1][-1] + 1);

	// 第七题
	//char* a[] =  "work","at","alibaba" ;
	//char** pa = a;
	//pa++;
	//printf("%s\\n", *pa);

	// 第六题
	//int aa[2][5] =  1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ;
	//int* ptr1 = (int*)(&aa + 1);
	//int* ptr2 = (int*)(*(aa + 1));
	//printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));

	// 第五题
	//int a[5][5];
	//int(*p)[4];
	 这个赋值操作本身其实就是不科学的. (强行把两个不同类型的指针赋值, 就是有很大风险的)
	//p = a;
	//printf("%p,%d\\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);

	// 第四题
	//int a[3][2] =  (0, 1), (2, 3), (4, 5) ;
	//int* p;
	//p = a[0];
	//printf("%d\\n", p[0]);
	//printf("%d\\n", a[0][0]);

	// 第三题
	//int a[4] =  1, 2, 3, 4 ;
	//int* ptr1 = (int*)(&a + 1);
	//int* ptr2 = (int*)((int)a + 1);
	//printf("%x,%x", ptr1[-1], *ptr2);

	// 第二题
	//printf("%p\\n", p + 0x1);  // 0x100020 ??   0x100014!!
	//printf("%p\\n", (unsigned long)p + 0x1);	// 0x100001
	//printf("%p\\n", (unsigned int*)p + 0x1); // 0x100004

	// 第一题
	//int a[5] =  1, 2, 3, 4, 5 ;
	//int* ptr = (int*)(&a + 1);
	//printf("%d,%d", *(a + 1), *(ptr - 1)); // 2 5

	//int a[3][4] =  0 ;
	//printf("%d\\n", sizeof(a));	// 48 
	//printf("%d\\n", sizeof(a[0][0])); // 4  a[0][0] 结果是 int 
	//printf("%d\\n", sizeof(a[0]));	// 16 a => int[3][4]  a[0] => int[4] 
	//printf("%d\\n", sizeof(a[0] + 1));	//   a => int[3][4]  a[0] => int[4]   a[0] + 1 => int[4] + 1 => int* 
	//printf("%d\\n", sizeof(*(a[0] + 1)));	// a[0] => int[4]   + 1 => int*     * => int
	//printf("%d\\n", sizeof(a + 1));		// 4    a => int[3][4]   + 1 就是把数组转成指向首元素的指针.  int(*)[4]
	//printf("%d\\n", sizeof(*(a + 1)));		// 16   a + 1 => int(*)[4] 再 * 结果就是 int[4] 
	//printf("%d\\n", sizeof(&a[0] + 1));		//     a[0] => int[4]  再 & 得到了 int(*)[4]  再 + 1 还是 int(*)[4]
	//printf("%d\\n", sizeof(*(&a[0] + 1)));	// a[0] => int[4] 再 & 还是 int(*)[4] 再+1 还是 int(*)[4] 再来 * 得到 int[4]
	//printf("%d\\n", sizeof(*a));		// a 是 int[3][4]  *a 会导致 a 先隐式转成指向首元素的指针 int(*)[4] , 再 * 得到 int[4]
	//printf("%d\\n", sizeof(a[3]));		// 16  sizeof 是编译期求值, 于是这个 a[3] 不会在运行时执行


	//char* p = "abcdef";
	//printf("%d\\n", sizeof(p));	// 4   p 是 char* 类型
	//printf("%d\\n", sizeof(p + 1));	// 4   p 是 char* 类型, p + 1 还是 char*
	//printf("%d\\n", sizeof(*p));		// 1   p 是 char* *p 就是 char 类型
	//printf("%d\\n", sizeof(p[0]));		// 1   p[0] => *(p + 0) => *p
	//printf("%d\\n", sizeof(&p));		// 4  p 是 char* &p => char**
	//printf("%d\\n", sizeof(&p + 1));		// 4  同上
	//printf("%d\\n", sizeof(&p[0] + 1));		// 4  p[0] 得到 char, & 得到 char* 再 + 1 还是 char*

	//printf("%d\\n", strlen(p));		// 6 从 a 开始, 找 6 个字符就找到了 \\0
	//printf("%d\\n", strlen(p + 1));		// 5 从 b 开始, 找 5 个字符就找到了 \\0
	//printf("%d\\n", strlen(*p));		// 未定义行为. *p 得到的是 char 'a'. strlen 需要的是 char* 类型. 原则上讲是不应该编译通过的. 但是 C 语言对于类型检查不严格. strlen 就会尝试从 'a' ascii 这个地址, 开始去找 \\0. 由于这个地址是非法内存. 
	//printf("%d\\n", strlen(p[0]));		// 未定义行为. 同上. 
	//printf("%d\\n", strlen(&p));			// 未定义行为.  &p 得到的是 char**, 本身内部存的地址, 是 p 变量本身的地址. 这个地址和 \\0 无关, 尝试去找, 能不能找到这个 \\0 , 这是完全不好说的. 
	//printf("%d\\n", strlen(&p + 1));		// 未定义行为. 原因同上
	//printf("%d\\n", strlen(&p[0] + 1));		// 5   p[0] 得到了 char 'a'. & 得到了 char*, 指向 'a', 再 + 1 得到 指向 'b' 的指针. 

	// " " 本身已经是字符串, 本身里面已经有 \\0 了. 
	// 得到的 arr 应该是一个 char[7]
	//char arr[] = "abcdef";
	//printf("%d\\n", sizeof(arr));  // 7
	//printf("%d\\n", sizeof(arr + 0)); // 4 arr 是 char[7], +0 就相当于隐式转成了 char*
	//printf("%d\\n", sizeof(*arr));	// 1  *arr 得到的是 'a' , char
	//printf("%d\\n", sizeof(arr[1])); // 1  arr[1] 得到的是 'b', char
	//printf("%d\\n", sizeof(&arr));  // 4  arr 是 char[7], &arr 是 char(*)[7] , 这也是指针类型. 
	//printf("%d\\n", sizeof(&arr + 1)); // 4 同上. 
	//printf("%d\\n", sizeof(&arr[0] + 1));  // 4 arr[0] 得到 char, 再 & 得到 char* , 再 +1 还是 char* 

	//printf("%d\\n", strlen(arr)); // 6  计算 strlen 的时候, 不算 \\0 本身. 
	//printf("%d\\n", strlen(arr + 0)); // 6  同上. 
	//printf("%d\\n", strlen(*arr));  // 未定义行为.  *arr 得到的是 'a'. char, 不是 const char* , 尝试把 'a' 的 ascii 码当做内存地址了, 并尝试访问这个地址的内存. 
	//printf("%d\\n", strlen(arr[1]));	 // 未定义行为. arr[1] 得到的是 'b'. char, 不是 const char*. 尝试把 'b' 的 ascii 值当做一个内存地址了. 并尝试访问这个地址的内存. 
	//printf("%d\\n", strlen(&arr));	// 6 &arr 得到的是数组指针, char(*)[7], 和 形参要求的 const char* 不同的. 虽然类型不匹配, 但是结果碰巧是对. 
	//printf("%d\\n", strlen(&arr + 1));  // 未定义行为了. 
	//printf("%d\\n", strlen(&arr[0] + 1));  // 5 arr[0] 得到 字符 'a', 再 & 得到了 指向 'a' 的指针. 再 +1 得到了 指向 'b' 的指针. 从这个位置开始, 往后找 \\0, 

	//char arr[] =  'a','b','c','d','e','f' ;
	//printf("%d\\n", sizeof(arr)); // 6  没有 \\0
	//printf("%d\\n", sizeof(arr + 0));  // 4  arr 本来是 char[6], +0 就触发了隐式转换. 就变成了 char* 
	//printf("%d\\n", sizeof(*arr));    // 1  arr 是 char[6], 本来是个数组, 但是在 * 运算中也隐式转成了 char*, 针对 char* 解引用, 结果就是一个 char
	//printf("%d\\n", sizeof(arr[1]));		// 1 arr 是 char[6] 进行 [1] 操作, 就得到了一个 char 'b'
	//printf("%d\\n", sizeof(&arr));		// 4  arr 是 char[6], &arr 得到了一个 char(*)[6]
	//printf("%d\\n", sizeof(&arr + 1));   // 4  arr 是 char[6], &arr 得到了 char(*)[6], 再 +1 结果仍然是 char(*)[6]
	//printf("%d\\n", sizeof(&arr[0] + 1));  // 4  arr[0] 得到了 char, 取地址, 得到了 char*, 再 + 1 仍然是 char* 

	// 代码中永远不能依赖未定义行为
	//printf("%d\\n", strlen(arr));  // 未定义行为.  arr 没有 \\0. 进行 strlen 就会出现数组下标越界. 
	//printf("%d\\n", strlen(arr + 0)); // 未定义行为. 和上面一样. 
	//printf("%d\\n", strlen(*arr));	// 未定义行为 arr 是 char[6], *arr 得到的是 char, 'a' 这个字符. 把 'a' 的 ascii 当做内存地址了. 这是一个非法地址, 尝试读取数据, 就会出现未定义行为. 
	//printf("%d\\n", strlen(arr[1])); // 同上. 这回访问的是 'b' 的 ascii 值对应的内存. 
	//printf("%d\\n", strlen(&arr));	// 未定义行为  &arr 得到的是数组指针. char(*)[6] , 虽然和形参类型不同, 但是大家都是指针, 里面存的地址相同. 这个时候也就相当于是从 'a' 地址开始往后找 \\0
	//printf("%d\\n", strlen(&arr + 1)); // 未定义行为 &arr 得到了一个 char(*)[6]. 再 + 1 还是 char(*)[6] . 指针 +1, 地址要跳过一个元素. 这一跳就把整个数组的内容都跳过了. 
	//printf("%d\\n", strlen(&arr[0] + 1));


	//int a[] =  1, 2, 3, 4 ;
	//printf("%d\\n", sizeof(a)); // 16
	//printf("%d\\n", sizeof(a + 0)); // 4  当前由于数组名参与了 + 0 运算, 隐式转成了指针. 
	//printf("%d\\n", sizeof(*a));   // 4 当前 a 参与了 * 运算, 也隐式转成了指针 int* .  针对 int* 解引用, 结果是一个 int
	//printf("%d\\n", sizeof(a + 1));  // 4 和第二个代码一样, 数组名参与了 + 1 运算, 隐式转成了 int* 
	//printf("%d\\n", sizeof(a[1])); // 4 a 是数组, [1] 取到下标为 1 的元素, 是一个 int

	//printf("%d\\n", sizeof(&a)); // 4 &a 得到一个数组指针. int(*)[4]
	//printf("%d\\n", sizeof(*&a));  // 16 &a 得到一个数组指针. int(*)[4], 针对这个数组指针 * 操作, 结果就得到了一个 int[4]
	//printf("%d\\n", sizeof(&*a));  // 4 a 是 int[4], *a, 其实就会先把 a 转成 int*, 然后 * 得到了一个 int. 然后再 & 就又得到了一个 int* 
	//printf("%d\\n", sizeof(&a + 1)); // 4 a 是 int[4], &a 是 int(*)[4], 再 + 1 仍然是 int(*)[4]
	//printf("%d\\n", sizeof(&a[0]));  // 4 a 是 int[4], a[0] 得到 int, 再 & 得到 int* 
	//printf("%d\\n", sizeof(&a[0] + 1)); // 4 a 是 int[4], a[0] 得到 int, 再 & 得到 int* , 再 + 1 结果仍然是 int* 


	//int arr[] =  9, 5, 2, 7, 3, 6 ;
	//int len = sizeof(arr) / sizeof(arr[0]);
	 bubbleSort 的调用者, 需要手动指定一个比较函数, 交给 bubbleSort
	 这个比较函数起到的效果, 就是在定义排序的比较规则. 
	 此时这个 less 函数并不是调用者自己来调用, 而是 由 bubbleSort 内部来进行调用. 

下一篇

以上是关于初始c笔记bing的主要内容,如果未能解决你的问题,请参考以下文章

初始c笔记bing

网络初始bing

c/c++bing(练习题)

c/c++bing(练习题)

C语言基础学习笔记+ C语言进阶学习笔记总结篇(坚持才有收获!)

使用 jquery 复制 bing 图片主页效果(淡入,然后淡出)