C语言入门教程 第8讲 指针的基本概念

“&” 与 “*”

取地址与指针运算符(取值运算)

“&” 对变量进行取地址运算:
&(变量名) => 获取变量的地址
如:

int i;
printf("%d", &i);  // 打印出地址

如:

scanf("%d", &i);  // 传入一个地址

而“*”作为指针运算符,当然我更乐意称它为取值运算:
*(变量名) => 将变量当做地址,到相应的地址取值

思考:

*(&(变量名)) 是什么?

int i = 6;
printf( "%d", *(&i) );

什么是指针变量?

指针变量就是用来存储地址的变量

任何变量都它存储的地址,这个地址是随机分配的。如:

int i = 10;

i 这个变量的地址,是系统随机分配的。而我们对其进行 “&” 运算之后就可以得到它的地址,并且 (&i) 这个表达式就是一个指向i的指针。

这个指针所指向的地址中存储的值则是:
*(&i) ==> i

声明与初始化

声明方式:

指针类型 * 指针变量名;

例如:

int *p1;
char *name;

初始化:

1)普通写法

int x; 
int *p;
p = &x;

2)省略写法

int x;
int *p = &x;

上述两种写法都声明了一个指针p,并且这个指针是指向变量 x 的
对于变量 x, (&x) 则是一个指向x的指针 (指针存放的就是地址, 而&运算得到的地址表达式也就是指向其本身的指针)
并且通过 *(指针) 取到这个地址中的值

常见错误

请不要人为的指派地址:

// 错误1
int *p;
p = 10010;   

// 错误2
int x = 20;
printf("%d", &(*x) );

// 正确形式:
int i, *p, *t;
p = &i;
t = p;

只能通过已有的变量传递

经典的错误 – Scanf函数

int score;
printf("请输入你的分数:n");
scanf("%d", score);

上述代码在编译时没有错,运行时会出现严重的错误

错误原因:
scanf() 函数后面的参数应该传入的是指针,而这里直接把 score 的值传了进去。

正确应该是:

int score;
printf("请输入你的分数:n");
scanf("%d", &score);

Swap交换两个变量

与第五讲中不同的是,使用指针到某个地址中取访问它的值,就没有了作用域的限制

#include<stdio.h>

void swap(int *x, int *y)
{
    int temp;
    temp = *x;
    *x = *y;
    *y = temp;
    printf("x=%d, y=%d n", *x, *y);
}

main()
{
    int i = 13, j = 45;
    swap(&i, &j);
    printf("i=%d, j=%dn", i, j);
}

本讲小结

1) “&” 和 “*”

取地址与取值运算符 ==> 互为逆运算

2)指针变量是什么?

指针变量就是用来存储地址的变量
如,&i 就是一个指向变量i 的指针
通过*(指针)取值

3)声明

int *p1;
char *name;

4)初始化

普通写法

int x; 
int *p;
p = &x;

省略写法

int x;
int *p = &x;

5)指针的作用
引用类型,传递地址,减少内存消耗

课后作业

现在有一个数组,存储的是一个同学的期中考试成绩。

int score[8] = { 75, 86, 70, 88, 62, 87, 69, 77 };

那么现在我们要做的事情是:

1)求总分,求平均分

2)用指针遍历数组,求最大值和最小值

附加题:
用一个二维数组存储八门课的名称,例如:

char course[8][256] = { "chinese", "English", ... }

再用二维数组,存储多个人的成绩,用指针遍历求出每门课的平均分

C语言入门教程 第9讲 指针与数组

Advertisements

移动设备如何通过wifi共享文件

条件1:要有一台电脑
条件2:有路由、有wifi

1.首先下载wampserver这个软件

下载地址:
地址1 32位
地址2 64位
地址3 百度网盘 推荐

下载好了之后,按照流程一步步安装下来 (wamp安装流程

装好之后运行可以看到右下角托盘有个wamp的图标,图标为绿色则表示运行正常。


打开浏览器在地址栏输入127.0.0.1 可以看到wamp的界面那就ok了 (127.0.0.1是默认本机地址,非局域网地址)

2.设置wamp为在线状态


左键点击wamp图标,点击最下面的put online
颜色变换,转绿之后正常

3.查看本机局域网ip


打开cmd,输入命令ipconfig
可以看到,笔者电脑上的局域网ip是192.168.1.100

接着打开浏览器,在地址栏输入192.168.1.100

看到wampserver的界面,万事ok

现在你已经成功的在局域网上搭建了一个网站(更多网站建设的信息,请咨询站长)

4.开始在局域网中共享资源

打开wamp安装目录下的www目录,或者通过右下角wamp图标左键点击www directory(www目录)


将原本自带的两个文件都删除


随后将你想要共享的资料直接放在这个目录即可


随后刷新浏览器页面,就会看到添加目录下的文件,这个时候你的资料已经共享在局域网上了。
只要能联上wifi的移动设备都可以访问到。


可以用手机打开局域网的本机ip地址看看


当然资源可以下载下来,而且下载速度是看你路由的参数,如果你的路由很给力的话,下载速度会比用USB传输快很多。

那么现在开始,什么平板电脑或者智能手机,只要能联上wifi的,都能轻松的从局域网中获取到资源。

PS:重新开机之后要手动打开wamp服务,图标为绿才能共享。

c语言入门教程 第7讲 数组

一维数组

同类元素的集合,称为数组

定义方式

数据类型 数组名 [常量表达式]; 举例:

int 	a[5];
float	score[8];
double	d[10];
char	name[256];

初始化


int a[3];
a[0] = 1;
a[1] = 2;
a[2] = 3;

int b[5] = { 1, 2, 3, 4, 5 };    // 省略写法

float score[8] = { 1.0, 1.2 };   // 后面未赋值则为零

char name[] = "Alan";            // 省略写法,单独定义时必须声明大小

一维数组的下标

数组的下标实际上是关于数组第一个元素的偏移量 比如,定义一个数组array[5]。它的第一个元素跟数组的第一个元素的偏移量为0 所以,数组的第一个元素应该是array[0] 数组的第二个元素跟数组的第一个元素偏移量为1 所以,数组的第二个元素应该是array[1] 以此类推,数组的第五个元素与第一个元素的偏移量为4 所以,数组array的第五个元素应该是array[4] 结论: 一位数组最后一个元素的下标为 (长度 – 1) 并且对于一个数组它的第几个元素的下标就是几减一

循环初始化:


#include <stdio.h>

main()
{
    int a[10], b[3], i;

    // 有规律的循环赋值
    for( i = 0; i < 10; i++ )
    {
        a[i] = i;
    }

    // 多次输入赋值
    for( i = 0; i < 3; i++ )
    {
        scanf("%d", b[i]);
    }
}

注意如果一次输入多个数用scanf循环去接收的话,空格也会被当做字符(或数值)来保存

一维数组遍历

#include <stdio.h>

main()
{
    int a[8] = { 1, 1, 2, 3, 5, 8, 13, 21 };
    int i;

    for( i = 0; i < 8; i++ )
    {
        printf("%d ", a[i]);
    }
}

一维数组应用示例

#include <stdio.h>

main()
{
    int a[8] = { 80, 90, 85, 84, 70, 76, 75, 83 };
    int i, max = 0, min = 100;

    for( i = 0; i < 8; i++ )
    {
        if( a[i] > max )
        {
            max = a[i];
        }else if( a[i] < min )
        {
            min = a[i];
        }
    }
    printf("最高分为:%d 最低分为:%d", max, min);
}

二维数组

定义

//数据类型 数组名 [常量表达式][常量表达式];

int 	a[56][3];
char	name[5][256];

初始化


// 1)分段赋值
int grade[2][3] = { {80,75,92}, {61,65,71} };

// 2)连续赋值
int a[2][3] = { 80, 75, 92, 61, 65, 71 };

// 3)连续省略赋值
int a[][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

二维数组的遍历


#include <stdio.h>

int main()
{
    int grade[4][3] = {82,77,76,90,87,56,87,48,75,86,86,66};
    int i, j;
    for( i = 0; i < 4; i++ )
    {
        for( j = 0; j < 3; j++ )
        {
            if( grade[i][j] < 60 )
            {
                printf("第%d位学生不及格");
                continue;
            }
        }
    }
}

本讲小结

一、数组由类型说明符、数组名、数组长度(数组的个数)三部分组成
int a[10]; float money[2][3]; // 注意下标

二、数组的初始化
1)声明之后一个个赋值
2)省略形式赋值: char name[] = “Sam”;

三、数组的遍历
通过while、do while、for等循环遍历

四、数组的作用
数组是程序设计中最常用的数据结构,属于构造类型。它将相同类型的数据连续组合在一起,简化了命名和赋值过程。相较单一的数据类型,能够更快更方便的处理更多的数据。

C语言入门教程 第8讲 指针的基本概念

c语言编译器 CL.exe

下载地址CL.7z
版权问题:
仅供学习交流,请于24小时内删除,本人不承担版权问题…

基本使用:

1.解压缩,例如解压缩到E盘根目录下

2.打开cmd命令行界面(快捷方式win+R输入cmd回车)
cd命令切换到CL/Bin目录下

cd E: 
cd /CL/Bin

3.可以用任何编辑器在这个目录下编写.程序,如notepad++或者系统自带的记事本.
比如在E:/CL/Bin目录下新建一个hello.c其中输入

#include<stdio.h>
main()
{
	printf("Hello world");
}

然后
在cmd中,这样来编译和链接:

CL.exe hello.c

不过由于环境尚未配置,所以会提示找不到include的stdio.h文件
这个时候将#include改成#include “../include/stdio.h”用相对路径去找即可
exe程序会直接生成在当前目录

配置使用(更改环境变量):

include配置

在环境变量新建INCLUDE
路径为E:/CL/include; (具体看你自己的路径)

lib配置

在环境变量新建LIB
路径为E:/CL/Bin; (本人直接将其放在了Bin目录下,你也可以抠出来新建一个Lib目录保存)

设置path路径

最后在path中新添加一个,路径的最前或最后加上你的Bin目录路径 (注意不要动path里面其他的路径,否则有惊喜)
路径为E:/CL/Bin;

这样配置完了之后就可以直接使用cmd在任意路径使用基础的c语言编译器

例如:
在C盘根目录下写一个test.c程序,然后打开cmd

cd C:
CL.exe test.c

即可编译

如果你心情好的话,还可以把CL.exe重命名
比如改成gcc.exe

调用的时候直接(.exe可以省略)

gcc hello.c

c语言入门教程 第6讲 编译预处理命令

预处理指令

#include 引用各种函数库
#define 定义常用的宏

条件编译

根据表达式的结果来决定要编译的内容
#if
#else
#elif
#endif

// 根据变量或宏等是否定义来决定要编译的内容
#ifdef
#ifndef

#include

// 1)两种形式:
#include <stdio.h>  // 到配置目录中找
#include "stdio.h"  // 从当前目录开始找,无则到配置目录中找

// 2)文件包含允许嵌套
// 文件A包含了文件B,文件B又包含了文件C,最终文件B和C都会被引入A文件

#define

宏定义,用一个标示符来表示一个字符串,这个字符串可以使常量、变量或表达式。在宏调用中,将用该字符串替换宏名。

#include <stdio.h>
// 1) 无参数宏
#define PI 3.14
#define M (a+b+c)/2.0

main()
{
  int a = 1, b = 2, c = 3;
  printf("面积为%f", PI*2*2);
  printf("%f", M);
}
// 2)带参数宏
#define f(x) x*x+3*x
#define Sum(a,b,c) a=b*c;b=c*a;a=b*c

printf("%d", 3*f(2));

PS:非值传递,而是传递形参字符

条件编译

#if (常量表达式) =====> 注意常量,非变量
仅当表达式为真,则编译它与 #endif 之间的代码

#include<stdio.h>

#define debug = 0
#define beta = 1
#define status = 1

main()
{
#if (status == debug)
    printf("程序调试中n");
#elif (status == beta)
    printf("程序测试中n");
#else
    printf("欢迎使用正式版!n");
#endif
}

#ifdef 如果有定义 (if define)
#ifndef 如果没定义 (if not define)

#ifndef PI
    define PI 3.14
#endif

#ifdef 和 #ifndef 主要是用来避免重定义

c语言入门教程 第7讲 数组

额外内容:
使用CL.exe编译c程序

c语言入门教程 第5讲 函数基本概念及作用域

// 初中
y = 3x + 2

// 高中
f(x) = 3x + 2

// c语言
int f(int x)
{
    return x * 3 + 2;
}

C语言中的函数

1.函数名
2.参数
3.返回值

#include <stdio.h>

/*
    sum函数名 返回值为int
    int a, int b 为sum的参数及其类型
    返回值为 ( a + b ) 这个表达式的值
*/
int sum(int a, int b)
{
    return a + b;
}

main()
{
    int i, j;
    printf("请输入两个数:n");
    scanf("%d%d", &i, &j);
    printf("%dn", sum(i, j)); // sum(参数,参数)的形式调用,返回两数之和
}

函数的作用域

#include <stdio.h>

void swap(int i, int j)
{
    int temp;
    temp = i; i = j; j = temp;
    printf("x=%d, y=%d", x, y);
}

main()
{
    int i = 30, j = 75;
    swap(i, j);
    printf("i=%d, j=%dn", i, j),
}

main()中的 i, j 与 swap() 中的 i,j 不是相同的变量
两个函数,是两个不同的内存块.两个变量名称相同,但不在同一个内存上
所以,如果其中某个变量有改变与另一个函数中的变量无关

c语言入门教程 第6讲 编译预处理命令