C语言知识点一 ——概述

C语言学习笔记(一)

学好一门语言就是要多看多练,C语言学习就是从最基本的hello world开始的。

/*
块注释,注释多行;注释内容不参与编译。
*/
// hello world   行注释
#include<stdio.h> //标准输入输出库,<>表示导入系统文件,""表示导入自定义文件
int main()    //表示数据类型,返回为int
{
	printf("Hello world!");
	return 0//函数返回值,和函数返回值对应
}

C语言简介

C语言有32个关键字,9种控制语句,34种运算符:
32个关键字 :不能用于其他用途;

autodoubleintstruct
breakelselongswitch
caseenumregistertypedef
charexternreturnunion
constfloatshortunsigned
continueforsignedvoid
defaultgotosizeofvolatile
doifstaticwhile

常量:整型常量,字符常量,浮点常量,枚举常量
整型常量:八进制:以0 开头,不包含8和9;十六进制:以0x或0X开头,包含a到f的字母。
字符常量:一个或多个字符构成,如‘x’。字符常量不包含’和换行符。
注:在没有显式说明情况下,enum类型中第一个枚举值为0,第二个为1,依次类推。

C程序编译
预处理:宏定义展开、头文件展开、条件编译等,同时会删除代码中注释。
编译:检查语法,将预处理后文件编译生成汇编文件。
汇编:将汇编文件生成目标文件(二进制文件)。
链接:把库链接到最终的可执行程序中去。
预处理:gcc -E test.c -o a.i
编译: gcc -S a.i -o a.s
汇编:gcc -c a.s -o a.o
链接:gcc a.o -o a
a.i

//原始代码
#include<stdio.h>
#define MAX 3
int main()
{
printf("%d",MAX);
return 0;
}
//预处理 a.i
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 367 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 410 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 411 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 368 "/usr/include/features.h" 2 3 4
# 391 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4
# 392 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4
...
typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;
...
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 942 "/usr/include/stdio.h" 3 4
# 2 "test.c" 2
# 2 "test.c"
int main()
{
printf("%d",3);
return 0;
}


//编译 a.s
	.file	"test.c"
	.section	.rodata
.LC0:
	.string	"%d"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	$3, %esi
	movl	$.LC0, %edi
	movl	$0, %eax
	call	printf
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609"
	.section	.note.GNU-stack,"",@progbits
//汇编,二进制文件
ELF\00\00\00\00\00\00\00\00\00\00>\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\A0\00\00\00\00\00\00\00\00\00\00@\00\00\00\00\00@\00
\00
\00UH\89\E5\BE\00\00\00\BF\00\00\00\00\B8\00\00\00\00\E8\00\00\00\00\B8\00\00\00\00]\C3%d\00\00GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609\00\00\00\00\00\00\00\00zR\00x\90\0

数据结构
字符串常量:
字符串是内存中一段连续的char空间,以‘\0’结尾。
字符串常量与字符常量不同:
‘a’ : 为字符常量;
“a” : 为字符串常量 ‘a’’\0’;
printf格式字符:

格式类型描述
%dint接收整数值并输出十进制整数
%ffloat单精度浮点数
%xunsigned int无符号16进制整数,abcd…
%cchar字符型,ASCII
%schar *字符串。以’\0’结尾
%pvoid *以十六进制形式输出指针
%%%输出一个百分号
int main()
{
	char ch='a';
	printf("%c\n",ch);
	ch=getchar();  //接收一个字符
	putchar(ch);  //输出一个字符
	return 0;
}

运算符
运算符:+,-,* ,/,%(取模)

int main()
{
	int a=10;
	int b=5;
	printf("%d",a%b);  //值为0
	return 0;
}

比较运算符:
==, !=, < ,>, <= , >=
逻辑运算符:
!,&&,||

程序流程结构
C基本支持的最基本三种结构:顺序结构,选择结构,循环结构。
选择结构:
if:

int main()
{
int score;
if(score>90) printf("PASS\n");
return 0;

三目运算符:

int main()
{
	int a=10,b=20,c;
	c=a>b?a:b;
	printf("c=%d\n",c);
}

switch:

int main()
{
	int score;
	scanf("%d",&score);
	switch(score/10) 
	case 1:
		break;
	case 2:
		break;
	default:
		break;
}

循环结构:
while:

int main()
{
	while(1)
	{
	}
}

do while:
for:

for(int i=0;i<10;i++)

跳转语句:
break: 跳出最近的内循环语句,执行后面的代码。
continue: 立即终止本次循环,并执行下一次循环。

基本声明:
int i;
int *b,*c,d; //d不是指针
初始化:
int j=15;

typedef:
推荐使用typedef而不是#define来创建新的类型名,后者无法正确的处理指针类型。

char *ptr_to_char;   //把变量ptr_to_char声明为一个指向字符的指针。

typedef char *ptr_to_char; //把标识符ptr_to_char作为指向祖父的指针类型的新名字
ptr_to_char    a;  //声明a是一个指向字符的指针

常量使用:
int const a;
const int a;
两种写法都可以,都是把a声明为一个整数,值不能被修改。

int  *pi; //一个指向整型的指针
int const *pci;// 一个指向整型常量的指针,可以修改指针的值,不能修改指向的值
int *const cpi;//一个指向整型的常量指针,指针为常量,无法修改,但可修改他指向的整型值
int const  *const cpci;//无论指针还是指向的值都不允许修改

链接属性:
当组成一个程序的各个源文件分别被编译之后,所有的目标文件以及那些从一个或多个库中引用的函数链接在一起,形成可执行程序。
链接属性一共有3种:external,inernal,none。
关键字extern 和static用于在声明中修改标识符的链接属性。如果某个声明在正常情况下具有external链接属性,在它前面加上static关键字可以使它的链接属性变为internal。
static int b; //链接属性:internal

typedef  char *a;
int  b;   //链接属性:extern
int c(int d) //c的链接属性:extern
{
	int e;
	int f(int g);  //f的链接属性:extern 
}
//其余标识符的链接属性均为:none
//extern属性,如果第二次声明,并不会更改第一次声明所指定的链接属性。

存储类型:
普通内存、运行时堆栈、硬件寄存器

int  a=5;  //a的链接属性为extern 
extern int b;//extern属性,不是必须写
static int c;// internal属性,a,b,c的存储类型为静态,但并不存储与堆栈中。
int d(int e)//d具有extern,e不具有链接属性
{
	int f=15;//f,b,g局部变量,不具有链接属性,f在每次调用时被初始化为15
	register int b;//初始值时垃圾
	static int g=20;//g的存储类型为静态,在程序开始时,被初始化为20,当函数调用时,不会重新初始化
	extern int a;//声明不需要,在前面的作用域内
	{
		int  e;//不具有链接属性
		int  a;//同名不能被访问
		extern int h; //extern属性,必须使用extern
	}
	{
		int x;
		int e;
	}
}
static int i()
{
}

操作符

a<<-5
对于有符号值,是采用逻辑移位还是算术移位取决于编译器。一个程序如果使用了有符号数的右移位操作,它就是不可移植的。

指针
未初始化和非法的指针

int *a;  //指针没有初始化,没办法预测后面赋值语句把1存储在a所指向的内存位置
*a=1;
int a=12;
int *b=&a;
int **c=&b;

/*****/
a                 12
b                 &a
*b                a,12
c                 &b
*c                b,&a
**c               *b,a,12

++、- -优先级比*高

C语言实践

hello world学习

// hello world
//两个斜杠是行注释
/*这是块注释,可以注释若干行*/

//导入标准库,<>表示导入系统文件,""表示导入自定义文件
#include<stdio.h>
//int表示函数的返回值是一个整数
//main是程序的主函数
int main()
{
	printf("Hello world!");
	//return 表示函数结束
	return 0}

打开文件学习:

int main()
{
	Mat img;
	//双斜杠表示一个斜杠,第一个是转义字符,一个正斜杠可以代替\\
	img = imread("D:/temp/0001.jpg");
	//img = imread("D:\\temp\\0001.jpg");
	imshow("test", img);
	waitKey(0);
	return 0;
}

输入输出:
在高版本VS内使用scanf会报错C4996,原因:在标准C库内的函数,很多函数内部是不进行参数检测的,这些可能导致内存异常,所以微软改写了很多函数。
解决方法:添加:#define _CRT_SECURE_NO_WARNINGS可消除警告。
或者:#pragma warning(disable:4996)

控制流:
if(表达式)
语句;
else
语句;

switch(表达式){
case 常量表达式:语句序列
case 常量表达式:语句序列
default: 语句序列
}

while(表达式)
语句

for(表达式;表达式;表达式)
语句

堆栈操作:
堆栈是存储器中专用的缓冲区,用于暂存寄存器数据或地址指针,push/pop就用于堆栈的操作:
1、子程序调用,为了保护现场,把所要用的寄存器中的内容先暂时保存起来,在子程序调用结束之前,按照先进后出的原则,把数据恢复。
2、有时候,需要临时用一下某些寄存器,也可用一下,凭个人喜好;
堆栈操作指令
堆栈是一个先进后出的主存区域,位于堆栈段中,使用SS段寄存器记录器段地址。栈只有一个出口,即当前栈顶。栈顶是地址较小的一端(低端),它用堆栈指针寄存器SP指定。堆栈的两种基本操作,对应两条基本指令:

指针学习

int x=1,y=2,z[10];
int *ip; //ip是指向int类型的指针
ip=&x;//ip指向x
y=*ip;//y的值为1
*ip=0;//x的值为0
ip=&z[0];//ip指向z[0]

字符复制

//strcpy 数组法
void strcpy(char *s ,char *t)
{
	int i=0;
	while((s[i]=t[i])!='\0')
		i++;
}
//指针法
void strcpy(char *s,char *t)
{
	while((*s=*t)!='\0')
	{
		s++;
		t++;
	}
}
//优化
void strcpy(char *s,char *t)
{
	while((*s++=*t++)!='\0');
}

结构体

struct point {
	int x;
	int y;
}
struct rect r,*rp=&r;
//以下是等价的
r.pt1.x
rp->pt1.x
(r.pt1).x
(rp->pt1).x 
struct {
	int len;
	char *str;
} *p;

++p->len;//将增加len的值,相当与++(p->len)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值