学C的第十八天【指针初阶:5. 指针和数组、6. 二级指针、7. 指针数组;初识结构体:1. 结构体的声明、2. 结构体成员的访问、3. 结构体传参;练习:3道和整数二进制数相关的练习】-3

简介: 正确示范:使用传址调用,运用 .操作符 和 ->操作符 )

正确示范:使用传址调用,运用 .操作符 ->操作符 

//访问
#include <stdio.h>
#include <string.h>
struct Stu
{
  int age;
  char name[20];
};
//第一种方法:对地址解引用,再使用 .操作符
//定义一个函数,对结构体成员进行赋值
void set_stu(struct Stu* ps)//t 的类型就是struct Stu
{
  (*ps).age = 20;
  //因为成员 name 是数组,数组名是首元素地址
  //t.name = "张三"; 
  //所以不能这样写,不能把 张三 放在地址上
  //应该把 张三 放在地址的空间里
  //strcpy()函数:字符串拷贝
  strcpy((*ps).name, "张三");
  //strcpy:把字符串拷贝到一个地方
  //把 张三这个字符串 拷贝到 t.name这个空间去
}
//第二种方法:直接使用 ->操作符
//定义一个函数,对结构体成员进行赋值
void set_stu(struct Stu* ps)//t 的类型就是struct Stu
{
  ps->age = 20;
  //因为成员 name 是数组,数组名是首元素地址
  //t.name = "张三"; 
  //所以不能这样写,不能把 张三 放在地址上
  //应该把 张三 放在地址的空间里
  //strcpy()函数:字符串拷贝
  strcpy(ps->name, "张三");
  //strcpy:把字符串拷贝到一个地方
  //把 张三这个字符串 拷贝到 t.name这个空间去
}
//定义一个函数,打印结构体变量
void print_stu(struct Stu t)
{
  printf("%s %d\n", t.name, t.age);
}
int main()
{
  struct Stu s = { 0 };
  //定义一个函数,对结构体成员进行赋值
  set_stu(&s);
  //定义一个函数,打印结构体变量
  print_stu(s);
  return 0;
}


a1dc5b92d0c44923b505ceb7fa6c7b75.png

3. 结构体传参

                 

(演示代码:传值传址调用)

//传参
#include <stdio.h>
struct S
{
  int data[1000];
  int num;
};
struct S s = { {1,2,3,4}, 1000 };
//方案1:结构体传参
void print1(struct S s)
{
  printf("%d\n", s.num);
}
//方案2:结构体地址传参
void print2(struct S* ps)
{
  printf("%d\n", ps->num);
}
int main()
{
  print1(s); //传结构体(变量)
  print2(&s); //传地址
  return 0;
}


ffe77cc7deb24bce82f1e1bbd303a445.png

结论:

结构体传参的时候,要传结构体的地址

练习:

           

1. 写一个函数返回参数二进制中 1 的个数

(第一种方法:%2 和 /2 取出每一位并判断)

//写一个函数返回参数二进制中 1 的个数。
//比如: 15    0000 1111    4 个 1
#include <stdio.h>
int number_of_1(unsigned int m)//要设置成无符号的,不然无法判断 负数
{
  int count = 0; //计数器
  while (m) //如果 m 不为0,说明二进制还有1
  {
    if (m % 2 == 1)//判断最低位
    {
      count++; //为1则计数器++
    }
    m /= 2; //相当于二进制去了一位
  }
  //一直判断直到m等于0,返回统计的1的个数
  return count;
}
int main()
{
  int n = 0;
  //输入:
  scanf("%d", &n);
  //定义一个计算二进制中1个数的函数
  int ret = number_of_1(n);
  printf("%d\n", ret);
  return 0;
}

image.png

(第二种方法:使用 移位操作符 位操作符

#include <stdio.h>
int number_of_1(int m)//要设置成无符号的,不然无法判断 负数
{
  int count = 0; //计数器
  int i = 0;
  for (i = 0; i < 32; i++) //二进制有32位,判断32次
  {
    if ( ( (m >> i) & 1) == 1)
    //移动 i位 后再 按位与1 ,判断最低位二进制值是否为 1
    //移动后 m 的值并没有变,所以可以一直移动
    {
      count++; //是 1 则计数++
    }
  }
  return count;
}
int main()
{
  int n = 0;
  //输入:
  scanf("%d", &n);
  //定义一个计算二进制中1个数的函数
  int ret = number_of_1(n);
  printf("%d\n", ret);
  return 0;
}

image.png

(第三种方法:

n = n & (n - 1) -- 这个表达式会让n的二进制中最右边的1消失

所以在n变成0之前,能执行几次,

就说明n二进制上有几个1

#include <stdio.h>
int number_of_1(int m)//要设置成无符号的,不然无法判断 负数
{
  int count = 0; //计数器
  while (m)//如果 m 不为0,说明二进制还有1
  {
    m = m & (m - 1);//去掉最右边的1
    count++; //计数器++
  }
  return count;
}
int main()
{
  int n = 0;
  //输入:
  scanf("%d", &n);
  //定义一个计算二进制中1个数的函数
  int ret = number_of_1(n);
  printf("%d\n", ret);
  return 0;
}

665345614a3e4cdd97a0a72a2b34fbea.png

2. 打印整数二进制的奇数位和偶数位

         

//获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
 #include <stdio.h>
int main()
{
  int n = 0;
  scanf("%d", &n);
  int i = 0;
  //打印奇数位
  printf("奇数位:");
  for (i = 30; i >= 0; i -= 2)
  //循环时是 偶数位:30 28 26.。。。
  {
    printf("%d ", (n >> i) & 1);
    //这里移位后是奇数位,按位与1 取出最低位 打印
  }
  printf("\n");
  printf("偶数位:");
  //打印偶数位
  for (i = 31; i >= 1; i -= 2)
    //循环时是 偶数位:31 29 27.。。。
  {
    printf("%d ", (n >> i) & 1);
    //这里移位后是偶数位,按位与1 取出最低位 打印
  }
  return 0;
}

image.png

3. 求两个数二进制中不同位的个数

           

//编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?
//输入例子 :
//1999 2299
//输出例子 : 7
#include <stdio.h>
int number_of_1(int m)
{
  int count = 0; //计数器
  while (m)//如果 m 不为0,说明二进制还有1
  {
    m = m & (m - 1);//去掉最右边的1
    count++; //计数器++
  }
}
int main()
{
  int m = 0;
  int n = 0;
  //输入
  scanf("%d %d", &m, &n);
  //异或:相同为0,相异为1
  //把 m 异或 n 后,有几个相异就有几个1,再计算下二进制中有几个1即可
  int ret = number_of_1(m ^ n);
  printf("%d", ret);
  return 0;
}

f7939d1ddeae48688563618537a7d8da.png

相关文章
|
1月前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
38 3
|
1月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
120 13
|
27天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
1月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
1月前
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
1月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
1月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
56 4
|
1月前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
48 2
|
1月前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
39 1
|
2月前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。