美文网首页
C语言提高

C语言提高

作者: hgzzz | 来源:发表于2020-10-31 12:50 被阅读0次

数据类型与变量

  1. 数据类型
    • 类型相同的数据具有相同的表示形式、存储格式和操作,程序中所以数据必须属于某种数据类型。
    • 为编译器提供分配内存大小的依据,数据类型本身没有内存空间。
    • 使用typedef给类型起别名方便使用。
    • void:无类型,用来定义指针 void *p,函数返回值,函数参数。
#include <stdio.h>

int main(int argc, char const *argv[])
{
  int arr[] = {1, 2, 3};
  printf("%d\n", sizeof(arr)); // 12

  // arr = 6422308 arr + 1 = 6422312
  // arr 表示数据手元素地址 + 1 加的是一个元素的长度4
  printf("arr = %d arr + 1 = %d\n", arr, arr + 1);

  // &arr = 6422308 &arr + 1 = 6422320
  // &arr 表示的是整个数组的首地址 + 1,加整个数组的长度12
  printf("&arr = %d &arr + 1 = %d\n", &arr, &arr + 1); 
  return 0;
}
  1. 变量:变量的使用要抓住生命周期和作用域两点。
    • 全局变量(包括静态(文件内使用),普通(可跨文件使用))。
    • 局部变量(函数中的变量,形参,函数内使用)。
    • 生命周期伴随程序结束:静态变量(包括全局和局部,存放在data区),全局变量。
    • 函数执行完成销毁:局部变量,形参。
    • 有些局部变量指向堆区地址,在函数执行结束时,形参销毁但是堆区地址不会自动回收,只有free()函数回收。

内存分区(stack、heap、data、bss、text)

  1. stack:栈区,存放函数执行过程中的局部变量和形参,函数调用完毕释放。
    • 栈区地址由高向低使用,栈区有一定的大小限制,超过会造成堆栈溢出问题。

指针、函数指针

  1. 数组在作为形参时会退化为指针,在接收数组参数时,形参可以直接写指针形式。
#include <stdio.h>

int func(int arr[]){
  return sizeof(arr);
}

int func1(int arr[3]){
  return sizeof(arr);
}

int func2(int *arr){
  return sizeof(arr);
}

int main(int argc, char const *argv[])
{
  int arr[3] = {1, 2, 3};
  printf("数组的长度为:%d\n", sizeof(arr));  // 12(int * 3)

  printf("func 数组形参的长度为:%d\n", func(arr)); // 4 32位系统中一个指针的长度

  printf("func1 数组形参的长度为:%d\n", func1(arr)); // 4

  printf("func2 数组形参的长度为:%d\n", func2(arr)); // 4
  return 0;
}
  1. 指针是大小固定(与编译器决定)的数据类型。
    • 指针变量存储一个地址,它通过这个地址访问对应的地址块。
  2. 二级指针做形参,接收一个一级指针的地址。
    • 在使用指针类型形参时,要先做判断,防止段错误。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void func(char **p, int *len){
  if(p == NULL || len == NULL){
    return;
  }
  char *temp = (char *)malloc(100);
  strcpy(temp, "hgzzz");
  *p = temp;
  *len = strlen(temp);
}

int main(int argc, char const *argv[])
{
  char *p = NULL;
  int len = 0;
  func(&p, &len);
  printf("%s  %d\n", p, len); // hgzzz  5
  return 0;
}

字符串处理

  1. 函数接收字符串数组。
#include <stdio.h>
#include <string.h>

void print_arr(char **str_arr ,int len){
  if(str_arr == NULL){
    return;
  }
  int i;
  for(i = 0; i < len; i++){
    printf("%s ", str_arr[i]);
  }
}

void sort_arr(char **str_arr ,int len){
  if(str_arr == NULL) {
    return;
  }
  int i,j;
  char *temp;
  for(i = 0; i < len - 1; i++){ // 快速排序
    for(j = i + 1; j < len; j++){
      if(strcmp(str_arr[i], str_arr[j]) > 0){
        temp = str_arr[i];
        str_arr[i] = str_arr[j];
        str_arr[j] = temp;
      }
    }
  }
}


int main(int argc, char const *argv[])
{
  char *str_arr[] = { "aaa", "vvv", "ccc", "bbb" };
  int len = sizeof(str_arr) / sizeof(str_arr[0]);

  printf("排序前\n"); // aaa vvv ccc bbb 
  print_arr(str_arr, len);

  sort_arr(str_arr, len);

  printf("\n排序后\n"); // aaa bbb ccc vvv 
  print_arr(str_arr, len);
  printf("\n");
  return 0;
}

sizeof()

  1. sizeof()是运算符,不是函数,sizeof()部分在编译之前就已经确定结果。
#include  <stdio.h>

int main(int argc, char const *argv[])
{
  int a;
  printf("int_len = %d\n", sizeof(a)); // int_len = 4

  char *p;
  printf("pointer_len = %d\n",sizeof(p)); // pointer_len = 4

  return 0;
}
  1. sizeof()可以求得void类型指针的长度,但是无法求得void类型变量的长度。因为这样的变量无法分配内存大小,所以你也定义不了。但是指针是存储的一个地址,地址是根据编译器的位数决定的,所以指针的大小是确定的,比如32位编译器分配的指针就是4个字节的大小。
#include  <stdio.h>

int main(int argc, char const *argv[])
{
  /* 
  void a; // error: variable or field 'a' declared void
  printf("void_variable_len = %d\n", sizeof(a));
  */
  void *p;
  printf("void_pointer_len = %d\n", sizeof(p)); // void_pointer_len = 4
}
  1. sizeof()求静态分配内存的数组的大小
#include <stdio.h>

int func(int arr[2]){
  return sizeof(arr);
}

int main(int argc, char const *argv[])
{
  int int_arr[2] = {0};
  printf("int_arr_len = %d\n", sizeof(int_arr)); // int_arr_len = 8

  char char_arr[3] = {'a', 'b', 'c'};
  printf("char_arr_len = %d\n", sizeof(char_arr)); // char_arr_len = 3

  // 字符串数组,默认结尾加上结束符'\0'
  char str_arr[] = "hgz";
  printf("str_arr_len = %d\n", sizeof(str_arr)); // str_arr_len = 4

  // 数组作为函数参数,形参退化成指针,提高运行效率
  printf("arr_arg_len = %d\n", func(int_arr)); // arr_arg_len = 4
  return 0;
}

数组

  1. 指针数组,数组里面存储指针类型的变量。
#include <stdio.h>

int main(int argc, char const *argv[])
{
  int i = 0;
  // 指针数组,数组里面存储指针类型
  char *str_arr[] = {"aaa", "bbb", "ccc"};
  for(i = 0; i < sizeof(str_arr)/sizeof(str_arr[0]); i++){
    printf("%s\n", str_arr[i]);
    printf("%d\n", sizeof(str_arr[i])); // 4
  }

  return 0;
}
  1. 数组指针,指向整个数组的指针,而不是首元素。
#include <stdio.h>

int main(int argc, char const *argv[])
{
  int arr[10] = {0};

  typedef int int_arr_10[10];
  int_arr_10 *p = NULL;
  p = &arr;
  // p = 6422276 p + 1 = 6422316 步长是一个数组的大小
  printf("p = %d p + 1 = %d\n", p, p+1);

  // 定义数组指针类型
  int(*q)[10];
  q = &arr;
  printf("%d\n", q);
  return 0;
}
  1. 二维数组
#include <stdio.h>

int main(int argc, char const *argv[])
{
  int arr[][2] = {{1, 2}, {3, 4}, {5, 6}};
  // 差8个字节,步长为一行
  printf("arr = %d arr+1 = %d\n", arr, arr+1); 
  // 差24字节,步长为整个二维数组的长度
  printf("&arr = %d &arr+1 = %d\n", &arr, &arr+1); 
  return 0;
}

相关文章

  • C语言提高

    数据类型与变量 数据类型类型相同的数据具有相同的表示形式、存储格式和操作,程序中所以数据必须属于某种数据类型。为编...

  • C语言实战开发篇-2 C语言基础

    目标:提高编程能力,形成编程思想,精通JAVA,C语言的使用 C语言和C++的区别 1.C语言面向过程,C++面向...

  • NCRE&MOOC

    二级C Cousera计算导论与C语言基础 中国大学MOOCC语言程序设计C语言程序设计——快速入门与提高 二级J...

  • 技术栈

    内核驱动 C语言提高 C++学习 java学习 python学习 shell学习 linux知识 数据结构及算法 ...

  • 12.C语言提高(二)

    1.二维数组的本质 二维数组的本质是一个数组指针,放宽来说多维数组的本质也是一个数组指针 int arr[i][j...

  • 13.C语言提高(三)

    1.结构体中指针变量的深拷贝和浅拷贝 疑问点记录: 这两行代码定义了一个字符指针p,他指向堆内存中一段空间,这一段...

  • 11.C语言提高(一)

    1.排序 形参中的数组,编译器会把他当作指针处理形参写在函数上,和写在函数内是一样的,只不过是写在函数上具有对外的...

  • C语言编程快速提高方法

    如果学习用C语言编写单片机程序的话,速度会很快,每天两个小时,大约用两个月就可以掌握基础的语法,编写规则,并且能...

  • C语言编程学习如何提高

    接触C/C++有那么久了但是一直不敢说自己真的懂C语言了,感觉自己一直在C/C++的道路上划水飘。现在就给大家来介...

  • Java学习(1)——简介

    什么是Java语言 编译型+解释型语言。通过解释方式来执行的语言。跨平台。相比C++简洁得多,提高了可靠性,除去了...

网友评论

      本文标题:C语言提高

      本文链接:https://www.haomeiwen.com/subject/pgqqgctx.html