21T2-COMP9024-week03 lec01

目录

Pointers 指针

Numeral Systems 进制

Decimal representation 十进制表示法

Binary representation 二进制表示法

Hexadecimal representation 十六进制表示法

Memory 存储

Pointers 指针

Pointer Arithmetic 指针算法

Pointers and Arrays 指针和数组

Arrays of Strings 字符串数组


Pointers 指针

Numeral Systems 进制

数字系统…用数字或其它符号表示数字的系统。

大多数文化都发展了十进制decimal system(以10为基础)

对于计算机来说,使用二进制binary(以2为基数)或十六进制hexadecimal system(以16为基数)是很方便的

Decimal representation 十进制表示法

  • Base is 10; digits 0 - 9
  • Example: decimal number 4705 can be interpreted as
    10^{3} + 7· 10^{2} + 0· 10^{1} + 5· 10^{0}

Binary representation 二进制表示法

  • Base is 2; digits 0 and 1
  • Example: binary number 1101 can be interpreted as
    2^{3} + 1· 2^{2} + 0· 2^{1} + 1· 2^{0}

Hexadecimal representation 十六进制表示法

  • The base is 16; digits 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
  • Example: hexadecimal number 3AF1 can be interpreted as
    16^{3} + 10· 16^{2} + 15· 16^{1} + 1· 16^{1}

❖ Exercise: Conversion Between Different Numeral Systems

  1. Convert 74 to base 2
  2. Convert 0x2D to base 10 // 16进制
  3. Convert 0b1011111000101001 to base 16  Hint: 1011111000101001 //二进制
  4. Convert 0x12D to base 2

Memory 存储

  • char … 1 byte    
  • int,float … 4 bytes    
  • double … 8 bytes

如果我们声明一个名为k变量,存储k的位置用&k表示,也称为k的地址

用十六进制表示法打印内存地址很方便

int k;
int m;

printf("address of k is %p\n", &k);
printf("address of m is %p\n", &m);
output:
address of k is BFFFFB80           
address of m is BFFFFB84

这意味着

k占用从bfffb80到bfffb83的四个字节

m占用从bfffb84到bfffb87的四个字节

注意使用%p作为地址的占位符(“指针”值)

int array[5];

for (i = 0; i < 5; i++) {
   printf("address of array[%d] is %p\n", i, &array[i]);
}
output:
address of array[0] is BFFFFB60                         
address of array[1] is BFFFFB64
address of array[2] is BFFFFB68
address of array[3] is BFFFFB6C
address of array[4] is BFFFFB70

❖ Application: Input Using scanf()

#include 
…
int answer;
printf("Enter your answer: ");
scanf("%d", &answer);

float e;
printf("Enter e: ");
scanf("%f", &e);

❖ Exercise: Using scanf

写一个程序

输入数字,检查是否是正数,将Collatz的过程应用于数字

#include 

void collatz(int n) {
   printf("%d\n", n);
   while (n != 1) {
      if (n % 2 == 0)
	 n = n / 2;
      else
	 n = 3*n + 1;
      printf("%d\n", n);
   }
}

int main(void) {
   int n;
   printf("Enter a positive number: ");
   if (scanf("%d", &n) == 1 && (n > 0))  /* test if scanf successful
                                            and returns positive number */
      collatz(n);
   return 0;
}

Pointers 指针

指针是一种特殊类型的变量,用来存储另一个变量的地址(内存位置)

指针的值是一个地址

指针占用内存空间,就像任何其他特定类型的变量一样

指针所需的内存单元数取决于计算机的体系结构:

旧电脑或只有64KB可寻址内存的手持设备:

2个存储单元(即16位),用于保存从0x0000到0xFFFF(=65535)的任何地址

具有4GB可寻址内存的台式机

4个存储单元(即32位),用于保存从0x00000000到0xffffff(=4294967295)的任何地址

现代64位计算机

8个内存单元(可以寻址264字节,但实际上内存量受到CPU的限制)

定义方式

*p = 'T';  // sets the value of c to 'T'
*运算符有时被描述为“取值”指针,以访问基础变量
// a potential pointer to any object of type char
char *s;

// a potential pointer to any object of type int
int *p;

❖ Examples of Pointers

int *p; int *q; // this is how pointers are declared
int a[5];
int x = 10, y;

 p = &x;      // p now points to x
*p = 20;      // whatever p points to is now equal to 20
 y = *p;      // y is now equal to whatever p points to
 p = &a[2];   // p points to an element of array a[]
 q = p;       // q and p now point to the same thing

❖ Exercise: Pointers

 output:
 1  #include 
 2
 3  int main(void) {
 4     int *ptr1, *ptr2;
 5     int i = 10, j = 20;
 6
 7     ptr1 = &i; 
 8     ptr2 = &j; 
 9
10     *ptr1 = *ptr1 + *ptr2; 
11     ptr2 = ptr1; 
12     *ptr2 = 2 * (*ptr2); //ptr2=ptr1=60
13     printf("Val = %d\n", *ptr1 + *ptr2);
14     return 0;
15  }
Val = 120

Can we write a function to "swap" two variables?

The wrong way:

void swap(int a, int b) {
   int temp = a;                     // only local "copies" of a and b will swap
   a = b;
   b = temp;
}

int main(void) {
   int a = 5, b = 7;
   swap(a, b);
   printf("a = %d, b = %d\n", a, b); // a and b still have their original values
   return 0;
}

只改变了function里面的值 函数不能直接改变主函数里定义的变量的值

在C语言中,参数是“按值调用”

对参数值所做的更改不会影响原始值

函数swap()尝试交换a和b的值,但失败了,因为它只交换副本,而不交换main()中的实际变量

我们可以通过传递指针作为参数来实现“引用模拟调用”

这允许函数更改变量的“实际”值

void swap(int *p, int *q) {
   int temp = *p;                  // change the actual values of a and b
   *p = *q;
   *q = temp;
}

int main(void) {
   int a = 5, b = 7;
   swap(&a, &b);
   printf("a = %d, b = %d\n", a, b);  // a and b now successfully swapped
   return 0;
}

Pointer Arithmetic 指针算法

指针变量包含一个地址值。

C知道所指向的对象的类型

它知道那个项目的大小

它可以计算下一个/上一个对象的位置

int a[6];   // assume array starts at address 0x1000
int *p;
p = &a[0];  // p contains 0x1000
p = p + 1;  // p now contains 0x1004

对于声明为T*p的指针(其中T是一个类型)

如果指针最初包含地址

执行p=p+k(其中k是常数)

将p中的值更改为A+k*sizeof(T)

k的值可以是正的,也可以是负的。

int a[6];   (addr 0x1000)       char s[10];   (addr 0x2000)
int *p;     (p == ?)           char *q;      (q == ?)
p = &a[0];  (p == 0x1000)       q = &s[0];    (q == 0x2000)
p = p + 2;  (p == 0x1008)       q++;      

Pointers and Arrays 指针和数组

通过数组进行迭代的另一种方法:

确定数组中第一个元素的地址

确定数组中最后一个元素的地址

设置指针变量以引用第一个元素

使用指针算法在元素之间移动

当地址超过最后一个元素时终止循环

int a[6];
int *p;
p = &a[0];
while (p <= &a[5]) {
    printf("%2d ", *p);
    p++;
}

21T2-COMP9024-week03 lec01_第1张图片

注:由于指针/数组连接a[i]==*(a+i)

Arrays of Strings 字符串数组

一种常见的指针/数组组合是命令行参数

这些是运行程序时指定的0个或多个字符串

假设您有一个名为seqq的可执行程序。如果在终端中运行此命令:

./seqq 10 20

然后seqq将得到2个命令行参数:“10”,“20”

21T2-COMP9024-week03 lec01_第2张图片

argv[]的每个元素都是

 指向字符数组开头的指针(char*)

   包含以\0结尾的字符串

More detail on how  argv is represented:
./seqq 5 20
21T2-COMP9024-week03 lec01_第3张图片

如果要访问命令行参数,main()需要不同的原型:

int main(int argc, char *argv[]) { ...

main(int argc,char *argv[ ])

1.argc为整数

2.argv为指针的指针(可理解为:char **argv or: char *argv[] or: char argv[][]   ,argv是一个指针数组

 注:main()括号内是固定的写法。

argc…存储命令行参数的数目+1   如果没有命令行参数,则argc==1

argv[]…存储程序名+命令行参数

argv[0]始终包含程序名

argv[1]、argv[2]、…是命令行参数(如果提供)

定义用于转换字符串的有用函数:

atoi(char *s) 将字符串转换为int

atof(char *s)   将字符串转换为double(也可以指定给float变量)

❖ Exercise: Command Line Arguments

写一个程序

检查单个命令行参数

如果不是,则输出失败消息并退出

将此参数转换为数字并检查它是否为正数

将Collatz的过程(练习3,第1周的习题集)应用于数字

#include 
#include 

void collatz(int n) {
   printf("%d\n", n);
   while (n != 1) {
      if (n % 2 == 0)
	 n = n / 2;
      else
	 n = 3*n + 1;
      printf("%d\n", n);
   }

int main(int argc, char *argv[]) {
   if (argc != 2) {
      printf("Usage: %s number\n", argv[0]);
      return 1;
   }
   int n = atoi(argv[1]);
   if (n > 0)
      collatz(n);
   return 0;
}

argv可以看作双指针(指向指针的指针)

⇒ main()的替代原型:

int main(int argc, char **argv) { ...
 仍然可以使用  argv[0]argv[1], …

你可能感兴趣的:(21T2,COMP9024)