第一节 初识C语言

2023-11-17

第一节 初识C语言





本章重点:

  • 什么是C语言
  • 第一个C语言程序
  • 数据类型
  • 变量、常量
  • 字符串+转义字符+注释
  • 选择语句
  • 循环语句
  • 函数
  • 数组
  • 操作符
  • 常见关键字
  • define定义常量和宏
  • 指针
  • 结构体


一. 什么是C语言

  1. 概述

自然语言:汉语,日语,英语……
人和人交流的语言

计算机语言:C,C++,JAVA……
人和计算机交流的语言,
已知计算机语言一共有上千种。

C语言是一种计算机语言,广泛应用于底层开发(操作系统,驱动程序……)。

在这里插入图片描述


  1. C语言标准

  二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制订了一套完整的美国国家标准语法,称为ANSIC,作为C语言最初的标准。目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。


二. 第一个C语言程序

  1. 使用vs2019创建C语言项目。

点击创建新项目

在这里插入图片描述


点击空项目,点击下一步

在这里插入图片描述


配置项目名称,项目位置,点击创建

在这里插入图片描述


项目创建成功

在这里插入图片描述


  1. 新建.C文件

右击源文件,点击添加-新建项

在这里插入图片描述


填写名称,更改位置,点击添加

在这里插入图片描述


  1. 写代码

写一个c语言程序,打印helloworld

//C语言中所有的字符都是英文的字符
#include<stdio.h>

//主函数 是程序的入口,写的C语言代码都是从main函数的第一行开始执行的
//main函数是必须有的,但是有且仅有一个
int main() {
	printf("helloworld\n");
	//printf 是库函数 - C语言的标准库中提供的一个现成的函数-直接可以使用
	//功能是在屏幕上打印信息
	//库函数的使用,是需要包含头文件的,printf需要的头文件叫:stdio.h
	return 0;
}

在这里插入图片描述


使用ctrl+f5将代码编译-链接-运行

在这里插入图片描述


三. 数据类型

C语言中常见数据类型:

在这里插入图片描述


int main(){
	//sizeof计算结果的单位是字节
	printf("%d\n", sizeof(char));
	printf("%d\n", sizeof(short));
	printf("%d\n", sizeof(int));
	printf("%d\n", sizeof(long));
	printf("%d\n", sizeof(long long));
	printf("%d\n", sizeof(float));
	printf("%d\n", sizeof(double));
	return 0;
}


在这里插入图片描述


在这里插入图片描述


四. 变量与常量

  1. 概述

不变的值是常量,变得值是变量。


  1. 定义变量
  • 只能由字母、数字和下划线组成
  • 不能以数字开头
  • 长度不能超过63个字符
  • 变量名中区分大小写的
  • 变量名不能使用关键字
  • 变量的名字尽量有意义


int main(){
	int age = 150;
	float weight = 45.5f;
	char ch = 'w';
	return 0;
}


在这里插入图片描述


  1. 变量的分类
    全局变量:在{}外边定义的变量就是全局变量
    局部变量:就是{}内部定义的变量就是局部变量
    当前局部和全局变量在一个地方都可以使用的时候,局部优先


int a = 100;//全局变量
int main(){
	int a = 1000;//局部变量
	{
		int b = 0;
		printf("%d\n", b);
	}
	printf("%d\n", a);
	return 0;
}


在这里插入图片描述


  1. 变量的使用
    写一个代码
    完成2个整数的相加,并输出结果
    printf 是输出函数
    scanf 是输入函数
int main()
{
	int a = 0;
	int b = 0;
	int s = 0;

	//输入2个值
	scanf("%d %d", &a, &b);//3 5
	//计算
	s = a + b;
	//输出
	printf("%d\n", s);

	return 0;
}

在这里插入图片描述


注意:若是遇到了scanf报错问题,详见博客:https://danbaku.blog.csdn.net/article/details/131155663


  1. 变量的作用域和生命周期
      作用域:
      通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
      1.局部变量的作用域是变量所在的局部范围。
      2.全局变量的作用域是整个工程。

例1:

#include<stdio.h>

int main() {
	{
		int a = 10;
		printf("%d", a);
	}
	return 0;
}


运行程序,代码正确。

在这里插入图片描述


把printf语句放在括号外面时,再次尝试运行代码:

#include<stdio.h>

int main() {
	{
		int a = 10;
	}
	printf("%d", a);
	return 0;
}


代码报错,运行失败。

在这里插入图片描述


报错显示为“未定义的标识符a”


出现此问题的原因就是作用域的问题,因为a的作用域就只在上面的花括号中,超出作用域范围。


因此:
  1.局部变量的作用域是变量所在的局部范围。


例2:

#include<stdio.h>

int a = 100;

int test() {
	printf("%d", a);
	return 0;
}

int main() {
	printf("%d\n", a);
	test();
	return 0;
}


运行成功,输出如下。

在这里插入图片描述


此时的a在test()和main()中均可调用。这里的a是全局变量。


因此:
  2.全局变量的作用域是整个工程。


全局变量的很强大,那么可以跨文件使用吗?

看如下例子:
首先新建了一个a.c文件,并在文件中定义a。

在这里插入图片描述


然后再回到之前的文件中,加入一句extern

#include<stdio.h>

extern int a;

int test() {
	printf("%d", a);
	return 0;
}

int main() {
	printf("%d\n", a);
	test();
	return 0;
}


运行成功,输出如下。

在这里插入图片描述


生命周期:
  变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段。
  1.局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
  2.全局变量的生命周期是:整个程序的生命周期。


  1. 常量
    C语言中的常量和变量的定义形式有所差异。
    C语言中的常量分为一下几种:
     字面常量(直接写出的值,例如:1,”a”等等)
     const 修饰的常变量
     #define定义的标识符常量
     枚举常量


例子如下:

#include<stdio.h>

//const常属性的
//修饰变量

int main() {
	int a = 10;
	printf("a=%d\n", a);
	a = 100;
	printf("a=%d\n", a);
	return 0;
}


运行成功,结果如下。

在这里插入图片描述


这时,a是一个变量,经过第二次的重新赋值后变为了100。


现在我们加上“const”去修饰变量a。

#include<stdio.h>

//const常属性的
//修饰变量

int main() {
	const int a = 10;
	printf("a=%d\n", a);
	a = 100;
	printf("a=%d\n", a);
	return 0;
}


此时运行代码,发现程序报错。

在这里插入图片描述


这时变量a变得不可修改。a就是const修饰的常变量,但是本质上a还是一个变量。
a是被const在语法层面上加入了一个限制,a具有了常属性。


那么如何证明a的本质上还是一个变量呢?


例子如下:

#include <stdio.h>

int main() {
	int arr[10] = { 0 };
	int n = 10;
	int arr2[n] = { 0 };
}


运行失败,代码报错。

在这里插入图片描述


修改代码,加上const。

#include <stdio.h>

int main() {
	int arr[10] = { 0 };
	const int n = 10;
	int arr2[n] = { 0 };
}


运行失败,代码仍然报错。

在这里插入图片描述


此时证明,a加上了const本质上还是变量,a只是具有了常属性。


  当然,如果你照着上面的步骤完成了编译运行,并且没有报错的情况,那么看看这个文件的后缀,如果文件后缀为.cpp,那么上面的代码是可以运行的,并且不会报错的。这是因为在C++中,是将const看作常量的。而c语言不是。所以,这也是为什么在前面说要将文件后缀改为.c的原因之一。

#include<stdio.h>
//#define定义标识符常量
#define A 100

int main() {
	printf("%d\n", A);
	int B = A;
	printf("%d\n", B);
}


运行成功,结果如下。

在这里插入图片描述


这个可以算作是常量,可以用上面的方法尝试证明,这里不做过多演示。

#include<stdio.h>

//枚举常量
//枚举:一一列举

//自定义类型,颜色
//枚举类型
enum color
{
	//枚举类型里面列的值是枚举常量
	red,   //0
	green, //1
	blue   //2
};

int main() {
	enum color a = red;
	printf("%d", a);
	return 0;
}


运行成功,结果如下。

在这里插入图片描述


值默认从0开始,依次递增1。值可以改,具体在后面的笔记中详细介绍。


五. 字符串+转义字符+注释

  1. 字符串
      C语言中有字符类型,但是没有字符串类型,那么在C语言中是如何表示字符串的呢?
      “hello world”这种有双引号引起来的一串字符称为字符串字面值,或者简称字符串。注意:字符串的结束标志是一个\0的转义字符,在计算字符串长度的时候\0是结束标志,不算作字符串内容。


如何观察到\0?
首先,生成一段空代码。

#include<stdio.h>

int main() {

	return 0;
}


然后按F10,开始调试。这里会弹出窗口和终端等东西,不用管。

在这里插入图片描述


注意行号左边是否有黄色箭头,有箭头就是进入了调试模式。

在这里插入图片描述


在上方菜单栏中依次点击:窗口-监视-监视1(1)。

在这里插入图片描述


在弹出的监视1中输入:”abcd”,输入完成后展开。这时我们便看到了\0。

在这里插入图片描述


字符串的本质是一串字符,可以存放在字符数组里面。

这里举个例子:

#include<stdio.h>

int main() {
	char arr1[] = "abc";
	char arr2[] = {'a','b','c'};
	return 0;
}


我们继续用刚刚的方法进行调试。

在这里插入图片描述


数组的区别显而易见。


这里需要注意,监视的时候一定要执行到return,否则会出现代码乱码等问题。例如下图。


如何判断执行到哪一句代码,只需要看黄色箭头。


在这里插入图片描述


调试监视器时,可以在把鼠标光标放在returen前面,这时会出现绿色箭头,点击即可。

在这里插入图片描述


我们可以再来研究一下有没有斜杠零的区别。
代码如下:

#include<stdio.h>

int main() {
	char arr1[] = "abc";
	char arr2[] = {'a','b','c'};
	printf("%s\n", arr1);
	printf("%s", arr2);
	return 0;
}


代码运行成功,但并非预期输出。

在这里插入图片描述

这里可以看出来,字符串中,隐藏着放着一个\0,而\0是字符串的结束标志。


我们对arr2手动加入\0,观察效果。

#include<stdio.h>

int main() {
	char arr1[] = "abc";
	char arr2[] = {'a','b','c','\0'};
	printf("%s\n", arr1);
	printf("%s", arr2);
	return 0;
}


代码运行成功。

在这里插入图片描述


现在,我们对字符串的长度进行研究。
例子如下:

#include<stdio.h>
#include<string.h>  //字符串头文件

int main() {
	char arr1[] = "abc";
	char arr2[] = {'a','b','c'};

	/*printf("%s\n", arr1);
	printf("%s", arr2);*/

	//strlen是一个库函数,求字符串长度的, 统计的是字符串中\0之前的字符个数
	printf("%d\n", strlen(arr1));
	printf("%d\n", strlen(arr2));//随机值
	return 0;
}


代码运行成功。

在这里插入图片描述


再次说明,一定要注意strlen库函数求字符串长度是不算上\0的。


  1. 转义字符
    转义字符,即转变原来的意思,
    假如我们要在屏幕上打印一个目录: c:\code\test.c
#include <stdio.h>
int main()
{
    printf("c:\code\test.c\n");
    return 0;
}


运行成功,但非预期结果。

在这里插入图片描述


#include <stdio.h>
int main()
{
    printf("c:\\code\\test.c\\n");
    return 0;
}


对代码进行转义,再次运行,得到正确结果。

在这里插入图片描述


下面列举出了C语言的常用转义字符。

在这里插入图片描述


注意:部分编译器会支持三字母词。大部分都是一些早期的编译器。举一些常见的参数值:??)的值是],??(的值是[。为了防止这种效果,只需要再前两个问号前面加入\,将其三字母词问号转换为正常问号。


举例:打印单引号和双引号

#include <stdio.h>
int main()
{
    //问题1:在屏幕上打印一个单引号',怎么做?
    //问题2:在屏幕上打印一个字符串,字符串的内容是一个双引号“,怎么做?
    printf("%c\n", '\'');
    printf("%s\n", "\"");
    return 0;
}


运行成功,结果如下。

在这里插入图片描述


  1. 注释
      代码中有不需要的代码可以直接删除,也可以注释掉。代码中有些代码比较难懂,可以加一下注释文字。
#include <stdio.h>
int Add(int x, int y)
{
    return x + y;
}
/*C语言风格注释
int Sub(int x, int y)
{
    return x-y;
}
*/
int main()
{
    //C++注释风格
    //int a = 10;
    //调用Add函数,完成加法
    printf("%d\n", Add(1, 2));
    return 0;
}


注释有两种风格:
 C语言风格的注释 /xxxxxx/
 缺陷:不能嵌套注释
 C++风格的注释 //xxxxxxxx
 可以注释一行也可以注释多行


六. 结构

  C语言是一个结构化的程序设计语言。共有三种结构,顺序结构、选择结构、循环结构。选择结构有两种,if和switch。循环结构有三种,while循环、for循环和do while循环。

  1. 选择语句

例子如下:

#include <stdio.h>
int main()
{
    int coding = 0;
    printf("你会去敲代码吗?(选择1 or 0):>");
    scanf("%d", &coding);
    if (coding == 1)
    {
        printf("坚持,你会有好offer\n");
    }
    else
    {
        printf("放弃,回家卖红薯\n");
    }
    return 0;
}


  1. 循环语句
    C语言中如何实现循环呢?
     while语句
     for语句
     do…while语句

例子如下:

//while循环的实例
#include <stdio.h>
int main()
{
    int line = 0;
    while (line <= 20000)
    {
        line++;
        printf("我要继续努力敲代码\n");
    }
    if (line > 20000)
        printf("好offer\n");
    return 0;
}


七. 函数

  函数的特点就是简化代码,代码复用。

例子如下:

#include <stdio.h>
int main()
{
    int num1 = 0;
    int num2 = 0;
    int sum = 0;
    printf("输入两个操作数:>");
    scanf("%d %d", &num1, &num2);
    sum = num1 + num2;
    printf("sum = %d\n", sum);
    return 0;
}

// 上述代码,写成函数如下:
#include <stdio.h>
int Add(int x, int y)
{
    int z = x + y;
    return z;
}
int main()
{
    int num1 = 0;
    int num2 = 0;
    int sum = 0;
    printf("输入两个操作数:>");
    scanf("%d %d", &num1, &num2);
    sum = Add(num1, num2);
    printf("sum = %d\n", sum);
    return 0;
}


八. 数组

  1. 数组定义
      C语言给了数组的定义:一组相同类型元素的集合。

例子如下:

#include<stdio.h>

int main() {
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//定义一个整形数组,最多放10个元素
	int arr2[10] = { 1,2,3,4,5 };//不完全初始化,剩余元素默认初始化为0
	return 0;
}


我们可以通过“监视”看到数组情况。

在这里插入图片描述


  1. 数组的下标
      C语言规定:数组的每个元素都有一个下标,下标是从0开始的。
      数组可以通过下标来访问的。

在这里插入图片描述


例子如下:

#include<stdio.h>

int main() {
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	printf("%d\n", arr[7]);
	arr[7] = 100;
	printf("%d\n", arr[7]);
	return 0;
}


运行代码成功,结果如下。

在这里插入图片描述


  1. 数组的遍历
    代码如下:
#include <stdio.h>

int main() {
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int i = 0;
	while (i < 10) {
		printf("%d\n", arr[i]);
		i++;
	}
}


运行代码成功,结果如下。

在这里插入图片描述


九. 操作符

  1. 算术操作符
    + - * / %
    /,除法运算时,如果两边都是整数,得到的商也是整数。
    %,取模操作符两端只能是整数,不能是小数。


  1. 移位操作符
    >> <<
    移位移动的是二进制位。


  1. 位操作符
    & ^ |
    也是使用二进制位进行计算。


  1. 赋值操作符
    = += -= *= /= &= ^= |= >>= <<=


  1. 单目操作符
    单目操作符只有一个操作数,注意区别于双目操作符(二元操作符)。
    ! 逻辑反操作
    - 负值
    + 正值
    & 取地址
    sizeof 操作数的类型长度(以字节为单位)
    ~ 对一个数的二进制按位取反
    -- 前置、后置-- 后置--,先使用,后减一;前置--,先减一,后使用
    ++ 前置、后置++ 后置++,先使用,后加一;前置++,先加一,后使用
    * 间接访问操作符(解引用操作符)
    (类型) 强制类型转换
    关于自增自减运算符的一些魔鬼考试题详见博客:https://danbaku.blog.csdn.net/article/details/131756318


  1. 关系操作符
    >
    >=
    <
    <=
    != 用于测试“不相等”
    == 用于测试“相等”


  1. 逻辑操作符
    && 逻辑与
    || 逻辑或


  1. 条件操作符(三目操作符)
    exp1 ? exp2 : exp3


  1. 逗号表达式
    exp1, exp2, exp3, …expN
    从左向右依次计算,整个表达式的结果是最后一个表达式的计算结果。


  1. 下标引用,函数调用和结构成员
    [] () . ->


十. 常见关键字

在这里插入图片描述

  C语言提供了丰富的关键字,这些关键字都是语言本身预先设定好的,用户自己是不能创造关键字的。


  1. auto
    自动,和类型有关。所有的局部变量都是auto类型,所以auto可省略。常见格式为 auto int a;


  1. break
    跳出当前循环,常用于循环和switch语句中。


  1. case
    用于switch语句中。


  1. continue
    继续,用于循环。


  1. default
    用于switch语句中。


  1. do
    常在do…while循环中。


  1. enum
    枚举,和类型有关。


  1. extern
    声明外部符号。


  1. register
    寄存器,与存储类型有关。


  1. signed
    有符号的,与类型有关。


  1. unsigned
    无符号的,与类型有关。


  1. static
    静态,与存储类型有关。是用来修饰变量和函数的。
    在C语言中static有三种使用方式。
     修饰局部变量-称为静态局部变量
     修饰全局变量-称为静态全局变量
     修饰函数-称为静态函数


先来说说static修饰局部变量。

例子如下:

#include<stdio.h>

void test()
{
	int i = 1;
	i++;//++i; i = i+1;
	printf("%d ", i);
}

int main()
{
	int j = 0;
	while (j < 5)
	{
		test();
		j = j + 1;
	}
	return 0;
}


运行代码成功,结果如下。

在这里插入图片描述


  上面代码的思路是:main函数中有while循环,一共循环5次,也就是调用了5次test函数。现在再来看看test函数,函数中有变量i,i的值为1,i自增,输出i,所以这时的结果是2。循环中一共调用5次test函数,每次调用i都被赋值为1并自增。所以一共输出了5个2。


修改代码,对于变量i加上static修饰。

代码如下:

#include<stdio.h>

void test()
{
	static int i = 1;
	i++;//++i; i = i+1;
	printf("%d ", i);
}

int main()
{
	int j = 0;
	while (j < 5)
	{
		test();
		j = j + 1;
	}
	return 0;
}

运行代码成功,结果如下:

在这里插入图片描述


  对于这个结果,不难理解,在这五次调用test函数时,i在调用时不会被重新赋值为1了,每一次i的值都是上一次i使用后的值。
  这时局部变量就是静态的局部变量。
  一个普通的局部变量进入函数创建,出函数销毁。但是被static修饰之后,进入函数时已经创建好了,出函数的时候也不销毁,多次调用函数时,共享一个变量。
  主管的感受:生命周期变长了,但是作用域不变,只能在局部范围内使用。


在这里插入图片描述

  本质是:普通的局部变量是放在栈区上的,但是被static修饰后,是存放在内存的静态区的,静态区的变量生命周期和全局变量的生命周期一样。


在这里我们仍可以用“监视”去看一看。

在代码窗口中我们可以看见static int i = 1这一句代码并没有被执行,而是直接跳到了下一行。这是因为在编译的时候就已经生成了该地址。

在这里插入图片描述


好,我们接下来继续看static修饰全局变量。

例子如下:

#include<stdio.h>

int g_val = 100;

void test()
{
	printf("test():%d\n", g_val);
}

int main()
{
	printf("%d\n", g_val);
	test();
	return 0;
}


运行代码成功,结果如下。

在这里插入图片描述


根据上述代码及结果,我们可以看到变量g_val是全局变量。接着对代码进一步进行改动。创建add.c,将全局变量放入add.c中。

在这里插入图片描述


再次编译代码,运行成功。

在这里插入图片描述


注意:extern的作用是声明来自外部文件的符号,上面截图中37行代码的是告诉编译器:g_val 是来自其他文件的。在C语言中每个.c文件都是单独经过编译器处理的。所以这里需要用extern进行声明。否则会报错。

全局变量是具有外部链接属性。这种属性决定了全局变量在多个文件之间可以互相使用。


再次修改代码,使用static修饰全局变量g_val。

代码如下:

在这里插入图片描述


运行代码失败,程序报错。

在这里插入图片描述


  这是因为static修饰全局变量的时候,将外部链接属性变成了内部链接属性。g_val变量被static修饰,使得这个全局变量只能在当前的.c文件内部使用,不能在其他的.c文件中使用了。给我们的感受:改变了作用域。


最后,我们来讨论一下static修饰函数。

  static修饰函数与static修饰全局变量用法上几乎没有区别。函数也是具有外部链接属性的。这种属性决定了函数是可以跨文件使用的。static修饰函数是把函数的外部链接属性改成了内部链接属性,使得函数只能在自己所在的.c文件中使用,不能在其他.c文件中使用。


  1. struct
    结构体,与类型有关。


  1. typedef
    类型重定义,类型重命名。


例子如下:

#include<stdio.h>

//将unsigned int 重命名为uint,所以uint也是一个类型名。
typedef unsigned int uint;

int mian() {
	//在这里a和b这两个变量类型是一样的
	unsigned int a = 0;
	uint b = 0;
	return 0;
}


  1. union
    联合体类型。


  1. volatile
    易变。


注意:以上关键字在用到的时候会逐个介绍。


十一. #define定义常量和宏

代码如下:

#include<stdio.h>
//define定义标识符常量
#define MAX 1000
//define定义宏
//宏可以有参数
//宏是替换
#define ADD(x, y) ((x)+(y))
#include <stdio.h>
int main()
{
    int sum = ADD(2, 3);
    printf("sum = %d\n", sum);

    sum = 10 * ADD(2, 3);
    printf("sum = %d\n", sum);

    return 0;
}


十二. 指针

  1. 内存
      内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。编号=地址=指针

在这里插入图片描述


  1. 变量的地址
      变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。取出变量地址如下:
#include <stdio.h>
int main()
{
    int num = 10;
    &num;//取出num的地址
       //注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)
    printf("%p\n", &num);//打印地址,%p是以地址的形式打印
    return 0;
}


代码运行成功,结果如下。

在这里插入图片描述


取地址一般取的是第一个字节的地址。

在这里插入图片描述


我们也可以使用vc++2019里面的内存窗口进行查看。

在这里插入图片描述


  1. 通过指针更改变量的值

例子如下:

#include<stdio.h>

int main()
{
	int a = 10;
	//& - 取地址操作符
	int * pa = &a;//0x0012ff48  -内存的编号==地址==指针, pa叫指针变量
	//* 是在说明pa是指针变量
	//int 是在说明pa指向的是int类型的变量
	*pa = 20;//* 解引用操作符 - 通过地址找到地址所指向的对象。*pa就等价于a

	printf("%d\n", a);
	return 0;
	return 0;
}


运行代码成功,结果如下:

在这里插入图片描述


以整型指针举例,可以推广到其他类型,如:

#include <stdio.h>
int main()
{
 char ch = 'w';
 char* pc = &ch;
 *pc = 'q';
 printf("%c\n", ch);
    return 0;
}


代码运行成功,结果如下:

在这里插入图片描述


总结:
 内存会被划分以字节为单位的一个个的内存单元
 每个内存单元都有编号,编号 =地址=指针
 C语言中创建的变量,其实是向内存申请一块空间,比如:int a = 10,就是向内存申请4个字节的空间,每个字节都有地址
 &a的时候,拿出的是4个字节中地址较小的那个字节的地址(编号)
 这个地址要存储起来,给一个变量,这个变量是用来存放地址(指针)所以叫指针变量:int *pa = &a;
 pa中存放的是a的地址,要通过pa中的地址找到a,怎么写?*pa–> 通过pa中的地址找到a *pa = 20;//本质是修改a


补充:
 编号 = 地址 = 指针
 指针变量:存放地址的变量
 口头语中说的指针:一般指的是指针变量


  1. 指针变量的大小
    指针变量的大小取决于地址的大小
    32位平台下地址是32个bit位(即4个字节)
    64位平台下地址是64个bit位(即8个字节)

例子如下:

#include <stdio.h>
int main()
{
    printf("%d\n", sizeof(char*));
    printf("%d\n", sizeof(short*));
    printf("%d\n", sizeof(int*));
    printf("%d\n", sizeof(double*));
    return 0;
}


运行代码成功,结果如下:

在这里插入图片描述


由此可得出结论:指针大小在32位平台是4个字节,64位平台是8个字节。


这里可以对vc++2019的位数进行更改来证明。

在这里插入图片描述

将x86改为x64

在这里插入图片描述


运行代码成功,结果如下:

在这里插入图片描述


十三. 结构体

结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。
这里只能使用结构体来描述了。

例子如下:

#include<stdio.h>

struct Stu
{
	char name[20];
	int age;
	float score;
};

int main()
{
	int num;

	struct Stu s1 = { "张三", 20, 88.0f };
	struct Stu s2 = { "李四", 18, 65.5f };
	struct Stu s3 = { "王五", 19, 99.8f };

	struct Stu* ps1 = &s1;

	printf("%s %d %f\n", ps1->name, ps1->age, ps1->score);

	//printf("%s %d %f\n", s1.name, s1.age, s1.score);
	//printf("%s %d %f\n", s2.name, s2.age, s2.score);
	//printf("%s %d %f\n", s3.name, s3.age, s3.score);

	//结构体变量.结构体成员
	//结构体指针->结构体成员

	return 0;
}



本篇博客为本人学习C语言时的详细笔记,如有错误之处,还望各位指正。
文章为原创,如要转载请注明出处

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第一节 初识C语言 的相关文章

  • 如何减少 MinGW g++ 编译器生成的可执行文件的大小?

    我有一个简单的 Hello world C 程序 在 Win XP 下由 MinGW g 编译器编译为 500kB 可执行文件 有人说这是由于iostream的库和静态链接libstdc dll Using s链接器选项有点帮助 减少了 5
  • 如何将 Q 格式整数转换为浮点数(反之亦然)?

    我四处搜寻 找不到一个很好的问题来回答这个问题 给定一个整数 使用Q Format https en wikipedia org wiki Q number format 如何将该数字转换为普通浮点类型 反之亦然 如何将浮点类型转换为Q F
  • C# 枚举到字符串自动转换?

    是否可以让编译器自动将我的 Enum 值转换为字符串 这样我就可以避免每次都显式调用 ToString 方法 这是我想做的一个例子 enum Rank A B C Rank myRank Rank A string myString Ran
  • java 1.8下无法启动eclipse

    java 1 8 升级后我无法启动 eclipse 附上错误截图 这是我的 eclipse 配置设置 我该如何解决 startup plugins org eclipse equinox launcher 1 3 0 v20120522 1
  • 计算移动的球与移动的线/多边形碰撞的时间(2D)

    我有一个多边形 里面有一个移动的球 如果球撞到边界 它应该反弹回来 My current solution I split the polygon in lines and calculate when the ball hits the
  • Microsoft JDBC 中的 JTDS 属性相当于什么?

    我正在将 JTDS 连接更改为 Microsoft JDBC 并且我看到存在于http jtds sourceforge net faq html http jtds sourceforge net faq htmlMicrosoft JD
  • Checkstyle - 方法按修饰符排序

    是否可以添加到 checkstyle 规则以按修饰符对类中的方法进行排序 我的意思是开头的公共方法和最后的私有方法 MethodsOrderCheck做这个工作 检查文档 https www qulice com qulice checks
  • 如何修改生成的SOAP请求?

    我正处于创建输出拦截器并从 SOAP 消息中获取 OuputStream 的阶段 但是 如何在将 SOAP 信封发送到端点之前对其进行修改呢 我想删除一些 xml 元素 一种方法是获取文档并通过 XSLT 转换运行它 您可以通过调用来获取拦
  • 如何构建一棵与或树?

    我需要一个支持 与 和 或 的树结构 例如 给定一个正则表达式 如ab c d e 我想把它变成一棵树 所以 一开始我们有两个 或 分支 它可以向下ab or c d e 如果你低头ab分支 你得到两个节点 a and b or a其次是b
  • C#:自定义转换为值类型

    是否可以将自定义类转换为值类型 这是一个例子 var x new Foo var y int x Does not compile 是否有可能实现上述情况 我需要超载一些东西吗Foo 您将必须重载强制转换运算符 public class F
  • 从 DataRow 单元格解析 int [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 如何从 DataRow 单元格解析 int 值 Int32 Parse item QuestionId ToString 这段代码可以工作 但看
  • Gremlin.net 文本包含等效项

    我正在使用 Gremlin net 库连接到 janus 图形服务器 我使用 cassandra 和弹性搜索进行数据存储和索引 在我使用的 gremlin 语言和 gremlin 控制台中文本包含在属性的文本中进行搜索 我正在使用混合索引
  • 选择合适的IDE

    您会推荐使用以下哪种 IDE 语言来在 Windows 下开发涉及识别手势并与操作系统交互的项目 我将使用 OpenCV 库来执行图像处理任务 之后 我将使用 win32 API 或 NET 框架与操作系统交互 具体取决于您建议的工具 性能
  • 如何隐藏或删除 Android HoneyComb 中的状态栏?

    如何隐藏或删除 Android HoneyComb 中的状态栏 每次运行应用程序时 我都会发现某些内容必须被状态栏覆盖 我尝试改变AndroidManifest xml 但没有任何改变 你不知道 它被认为是永久的屏幕装饰 就像电容式主页 菜
  • C 变量声明的效率 [重复]

    这个问题在这里已经有答案了 例如 在 C 中声明一个变量需要多长时间int x or unsigned long long var 我想知道它是否会让我的代码在类似的事情中更快 for conditions int var 0 code 这
  • 如何在 Servlet 中打开弹出窗口,然后重定向页面

    我想在调用 servlet 时打开一个弹出窗口 然后想将 servlet 重定向到某个 jsp page 这就是我所做的 protected void doGet HttpServletRequest request HttpServlet
  • Boost.asio和异步链,unique_ptr?

    我对异步编程不太熟悉 我有一个问题 我的问题如下 给出 boost asio 中 C 11 的 echo server 示例 http www boost org doc libs 1 60 0 doc html boost asio ex
  • 从脚本启用/禁用 GameObject 组件 [Unity3D]

    我需要获取一个脚本中设置的布尔值 放入名为 bouclier 的变量 以启用或禁用游戏对象 该变量位于游戏对象 Player 中 此处右下角 我需要启用或禁用这个游戏对象 Bouclier01 为此 我将脚本附加到游戏对象 Bouclier
  • 在windows + opengl中选择图形设备

    我知道如何使用 openGL 打开窗口 使用 Win32 或其他工具包 但是当系统有2块显卡时 如何选择要渲染的图形设备 我的编程语言是 C 我专注于 Windows 但任何示例都将受到欢迎 编辑 也许更好地解释我的问题是个好主意 以便添加
  • 将一个 IEnumerable 拆分为多个 IEnumerable

    我是 linq 新手 我需要根据指示器将 Couple string text bool Indicator 类型的 IEnumerable 拆分为多个 IEnumerable 我尝试使用skipWhile 和 TakeWhile 但没有找

随机推荐

  • 刷脸支付不带手机钱包一样可以买单

    今年 移动支付加快脚步 迅速腾飞 其中最受国内外各大企业商户重视的 应该属去年开始投入使用的刷脸支付设备了与扫描二维码等很多移动收款方法 刷脸 支付的应用更为方便 支付的效率更高 安全性更强 无疑速决了很多当前的短处 手机扫码签约免密支付
  • Eclipse打开时出现failed to create the java virtual machine...

    一 问题分析 关于Eclipse出现failed to create the java virtual machine 等情况 1 重装系统之后会发现eclipse很意外的打不开 2 有时候Eclipse使用的时间过长 3 以上情况都会出现
  • vue-router设置默认路由

    git仓库 https github com xiaoli0510 vue router vue使用vue router步骤 1 安装并创建实例 npm install vue router 2 新建router 文件夹和router js
  • libvirt介绍

    libvirt是为了更方便地管理各种Hypervisor而设计的一套虚拟化库 libvirt作为中间适配层 让底层Hypervisor对上层用户空间的管理工具 virsh virt manager 做到完全透明 因为libvirt屏蔽了底层
  • 云原生Java架构师的第一课阿里云部署docker2- (docker实战-安装mysql)

    docker安装成功 后面就只需要去找对应的网站进行镜像下载安装就可以安装任意版本的数据库 而不需要考虑Linux服务器版本和架构 1 拉取 MySQL 镜像 去docker hub 找到mysql镜像 上面有所有的mysql版本和拉取镜像
  • 【网安神器篇】——hydra爆破工具

    作者名 Demo不是emo 主页面链接 主页传送门创作初心 舞台再大 你不上台 永远是观众 没人会关心你努不努力 摔的痛不痛 他们只会看你最后站在什么位置 然后羡慕或鄙夷座右铭 不要让时代的悲哀成为你的悲哀专研方向 网络安全 数据结构 每日
  • 用photoshop拼接一个七巧板图案

    转自 https jingyan baidu com article 215817f7a1f6fb1eda1423f8 html 图片处理软件图片市场是一个常见的工具软件 我们在使用时可以自己发掘一些有意思的功能 笔者从旋转拼接角度 以一个
  • 8-3编码器,3-8译码器的verilog实现

    在数字系统中 由于采用二进制运算处理数据 因此通常将信息变成若干位二进制代码 在逻辑电路中 信号都是以高 低电平的形式输出 编码器 实现编码的数字电路 把输入的每个高低电平信号编成一组对应的二进制代码 设计一个输入为8个高电平有效信号 输出
  • 回到十七世纪,让我来编算一本常用对数表(对数结果是小数,要有分数的思想,指数的幂是分数,这样可以实现小数分数转化位整数的幂的求法)

    原文地址 回到十七世纪 让我来编算一本常用对数表作者 小牛 自十八 九岁学习了对数后 就觉得造对数表真不简单 据说十七世纪那时 说如果谁发现了对数表上有一个数字错 就奖一两黄金 据百科百度 纳皮尔 1550 1617年 苏格兰数学家 对数的
  • GBK/GBK2312字库寻址及使用原理

    一 字符编码 1 1 ASCII编码 我们知道 我们所见到的所有字符编码 对于计算机来说都是0 1 更具不同位上的0 1 一个字节 8位 共有256中排列方式 因此一个字节就可以表示256个不同的字符 在这个前提下 ASCII编码就由美国制
  • 因材施教,有道发布“子曰”教育大模型,落地虚拟人口语教练等六大应用

    因材施教的教育宗旨下 大模型浪潮中 网易有道凭借其对教育场景的深入理解和对商业化的理性思考 为行业树立了垂直大模型的典范 7月26日 教育科技公司网易有道举办了 powered by 子曰 教育大模型应用成果发布会 会上重磅推出了国内首个教
  • 游戏与创新

    一 严肃游戏的概念 严肃游戏的出现 最早可以追溯到公元前1400年 当时在古埃及 有一款名为播棋的棋类游戏 这种游戏以植物种子或石子作为道具 在地面或棋盘上 目的是把对方的棋子吃掉 同时 播棋也在日常交易中 被用作计算数量的商业辅助工具 严
  • 5G 速率介绍

    本文就对如何计算最大速率不做介绍 主要介绍的是NSA和SA速率的差别 以及上下行速率的差异 由于5G单用户下行可以到4流 上行可以到2流 而且上下行都支持256QAM 2 6G频率 5ms单周期 配置下 NSA和SA终端下行峰值速率约1 6
  • 用FFmpeg制作WebP动图

    去年写过一篇文章 是教大家用FFmpeg制作GIF动画的 今天在讨论到项目中碰到的一个 apng动画素材引起的程序崩溃时 有位同学建议 我们为啥不用WebP来代替 apng 是啊 why not 网上搜到一篇文章 自己试了一下 发现强大的F
  • SQL Server Management Studio (SSMS) 指定端口Port连接, 用逗号, 例如: localhost,1433

    Microsoft SQL Server Management Studio SSMS 指定端口连接 用 逗号 例如 localhost 1433 localhost 等效 localhost 逗号 1433
  • QT 解决“ qt creator 修改UI后,运行无改变”问题

    只需要将 项目 中的 Shadow build 勾选去掉 重新构建项目 运行即可看到修改后的效果
  • 三、-切换frame&css选择器

    等待元素出现 隐式等待 用WebDriver 对象的implicitly wait方法 这个方法有一个参数 指明等待最长时间 driver implicitly wait 10 显式等待 Selenium里面还有一种称之为显式等待的 可以为
  • Spring的自动装配 byName和byType的区别

    Spring的自动装配 好处 大幅度减少Spring配置 坏处 依赖不能明确管理 可能会有多个bean同时符合注入规则 没有清晰的依赖关系 在装配的时候会有两种方式 byName和byType两种 byName 根据属性名自动装配 此选项将
  • el-checkbox如何同时获得value值和label的值

    在使用el checkbox时有时候需要往后台传送value值 定义的code 和label值 el checkbox组件默认获取的都是label属性中的值 如果label中设置的是code 那如何获取el checkbox的显示文字 la
  • 第一节 初识C语言

    第一节 初识C语言 目录 一 什么是C语言 二 第一个C语言程序 三 数据类型 四 变量与常量 五 字符串 转义字符 注释 六 结构 七 函数 八 数组 九 操作符 十 常见关键字 十一 define定义常量和宏 十二 指针 十三 结构体