sizeof(一)

本文详细介绍了C/C++中sizeof运算符的功能与用法,包括基本数据类型、指针、数组、字符串、引用、结构体及类的sizeof计算规则。

0.关键字:sizeof,字节对齐,类型大小

前向声明:
    sizeof,一个其貌不扬的家伙,引无数菜鸟竟折腰.

    小虾我当初也没少犯迷糊,秉着“辛苦我一个,幸福千万人”的伟大思想,我决定将其尽可能详细的总结一下。


    但当我总结的时候才发现,这个问题既可以简单,又可以复杂。所以本文有的地方并不适合初学者,甚至都没有必要大作文章。但如果你想“知其然,更知其所以然”的话,那么这篇文章对你或许有所帮助。
   

    菜鸟我对C++的掌握尚未深入,其中不乏错误,欢迎各位指正啊

1. 定义:
    sizeof是何方神圣?

    sizeof 乃 C/C++ 中的一个操作符(operator)是也。简单说其作用就是返回一个对象或者类型所占的内存字节数。

MSDN上的解释为:

The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type (including aggregate types).This keyword returns a value of type size_t.

    其返回值类型为size_t,在头文件stddef.h中定义。这是一个依赖于编译系统的值,一般定义为

typedef unsigned int size_t;

    世上编译器林林总总,但作为一个规范,它们都会保证char、signed char和unsigned char的sizeof值为1,毕竟char是我们编程能用的最小数据类型。

2. 语法:
    sizeof有三种语法形式,如下:
    1) sizeof( object );    // sizeof( 对象 );
    2) sizeof( type_name ); // sizeof( 类型 );
    3) sizeof object;       // sizeof 对象;

所以,
int i;
sizeof( i );     // ok
sizeof i;        // ok
sizeof( int );   // ok
sizeof int;      // error

既然写法2可以用写法1代替,为求形式统一以及减少我们大脑的负担,第2种写法,忘掉它吧!

实际上,sizeof计算对象的大小也是转换成对对象类型的计算。也就是说,同种类型的不同对象其sizeof值都是一致的。

这里,对象可以进一步延伸至表达式,即sizeof可以对一个表达式求值。编译器根据表达式的最终结果类型来确定大小,一般不会对表达式进行计算。

例如:

sizeof( 2 );        // 2的类型为int,所以等价于 sizeof( int );
sizeof( 2 + 3.14 ); // 3.14的类型为double,2也会被提升成double类型,所以等价于 sizeof( double );

    sizeof也可以对一个函数调用求值,其结果是函数返回类型的大小,函数并不会被调用。我们来看一个完整的例子:

*********************************************************

char foo()
{
    printf("foo() has been called./n");
    return 'a';
}
int main()
{
    size_t sz = sizeof( foo() );   // foo() 的返回值类型为char,所以sz = sizeof(char),但函数foo()并不会被调用
    printf("sizeof( foo() ) = %d/n", sz);
}

*********************************************************

C99标准规定,函数、不能确定类型的表达式以及位域(bit-field)成员不能被计算sizeof值,即下面这些写法都是错误的:

    sizeof( foo );     // error
    void foo2() { }
    sizeof( foo2() );  // error
    struct S
    {
        unsigned int f1 : 1;
        unsigned int f2 : 5;
        unsigned int f3 : 12;
    };
    sizeof( S.f1 );   // error

注意:sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。

  如sizeof(max)若此时变量max定义为int max(),sizeof(char_v) 若此时char_v定义为char char_v [MAX]且MAX未知,sizeof(void)都不是正确形式。
3. sizeof的常量性


    sizeof的计算发生在编译时刻,所以它可以被当作常量表达式使用。如:

char ary[ sizeof( int ) * 10 ];   // ok

最新的C99标准规定sizeof也可以在运行时刻进行计算。如下面的程序在Dev-C++中可以正确执行:

int n;
n = 10;        // n动态赋值
char ary[n];   // C99也支持数组的动态定义
printf("%d/n", sizeof(ary)); // ok. 输出10

但在没有完全实现C99标准的编译器中就行不通了,上面的代码在VC6中就通不过编译。所以我们最好还是认为sizeof是在编译期执行的,这样不会带来错误,让程序的可移植性强些。


4. 基本数据类型的sizeof

这里的基本数据类型指short、int、long、float、double这样的简单内置数据类型。由于它们都是和系统相关的,所以在不同的系统下取值可能不同。这务必引起我们的注意,尽量不要在这方面给自己程序的移植造成麻烦。

一般的,在32位编译环境中,sizeof(int)的取值为4。


5. 指针变量的sizeof

学过数据结构的你应该知道指针是一个很重要的概念,它记录了另一个对象的地址。既然是来存放地址的,那么它当然等于计算机内部地址总线的宽度。所以在32位计算机中,一个指针变量的返回值必定是4(注意结果是以字节为单位)。可以预计,在将来的64位系统中指针变量的sizeof结果为8。

*********************************************************

char* pc = "abc";
int* pi;
string* ps;
char** ppc = &pc;
void (*pf)(); // 函数指针
sizeof( pc ); // 结果为4
sizeof( pi ); // 结果为4
sizeof( ps ); // 结果为4
sizeof( ppc );// 结果为4
sizeof( pf ); // 结果为4

*********************************************************

指针变量的sizeof值与指针所指的对象没有任何关系,正是由于所有的指针变量所占内存大小相等,所以MFC消息处理函数使用两个参数WPARAM、LPARAM就能传递各种复杂的消息结构(使用指向结构体的指针)。


6. 数组的sizeof

数组的sizeof值等于数组所占用的内存字节数,如:

char a1[] = "abc";
int a2[3];
sizeof( a1 ); // 结果为4,字符 末尾还存在一个NULL终止符
sizeof( a2 ); // 结果为3*4=12(依赖于int)

一些朋友刚开始时把sizeof当作了求数组元素的个数,现在,你应该知道这是不对的。那么应该怎么求数组元素的个数呢?

Easy,通常有下面两种写法:

int c1 = sizeof( a1 ) / sizeof( char );    // 总长度/单个元素的长度
int c2 = sizeof( a1 ) / sizeof( a1[0]);    // 总长度/第一个元素的长度


写到这里,提一问,下面的c3,c4值应该是多少呢?

*********************************************************

void foo3(char a3[3])
{
    int c3 = sizeof( a3 ); // c3 ==
}
void foo4(char a4[])
{
    int c4 = sizeof( a4 ); // c4 ==
}

*********************************************************

也许当你试图回答c4的值时已经意识到c3答错了,是的,c3!=3。

这里函数参数a3已不再是数组类型,而是蜕变成指针。相当于char* a3,为什么仔细想想就不难明白。

我们调用函数foo1时,程序会在栈上分配一个大小为3的数组吗?不会!

数组是“传址”的,调用者只需将实参的地址传递过去,所以a3自然为指针类型(char*),c3的值也就为4。


7.string的sizeof
一个string的大小与它所指向的字符串的长度无关

*********************************************************
string st1("blog.sina.com.cn");
string st2("majianan");
string st3;
string *ps = &st1;
cout << "st1: " << sizeof(st1) << endl;
cout << "st2: " << sizeof(st2) << endl;
cout << "st3: " << sizeof(st3) << endl;
cout << "ps: " << sizeof(ps) << endl;
cout << "*ps: " << sizeof(*ps) << endl;
*********************************************************

输出结果为:
st1: 28
st2: 28
st3: 28
ps: 4
*ps: 28
*********************************************************
对于不同的STL,String类的结构定义会有所不同
所以不同的工具,例如VC++,和.NET,结果会有所不同,
在VC++6.0中(我的机器)结果是16
在.NET2003中结果是28
但是对于同一个编译器,那么它的结果都是一定的


8.引用的sizeof

sizeof操作符应用在引用类型上的时候,返回的是包含被引用对象所需的内存长度(即被引用对象的大小)

*********************************************************
cout << "short:/t" << sizeof(short) << endl;
cout << "short*:/t" << sizeof(short*) << endl;
cout << "short&:/t" << sizeof(short&) << endl;
cout << "short[4]:/t" << sizeof(short[4]) << endl;
cout << "int&:/t" << sizeof(int&) << endl;
*********************************************************

输出结果为:
short: 2
short*: 4
short&: 2
short[4]: 8
int&: 4


9. 结构体的sizeof

这是初学者问得最多的一个问题,所以这里有必要多费点笔墨。让我们先看一个结构体:

struct S1
{
    char c;
    int i;
};

问sizeof(s1)等于多少?

聪明的你开始思考了,char占1个字节,int占4个字节,那么加起来就应该是5。

是这样吗?

你在你机器上试过了吗?

也许你是对的,但很可能你是错的!

VC6中按默认设置得到的结果为8。

    Why?为什么受伤的总是我?

请不要沮丧,我们来好好琢磨一下sizeof的定义 —— sizeof的结果等于对象或者类型所占的内存字节数。好吧,那就让我们来看看S1的内存分配情况:

S1 s1 = { 'a', 0xFFFFFFFF };

定义上面的变量后,加上断点,运行程序,观察s1所在的内存,你发现了什么?

以我的VC6.0为例,s1的地址为0x0012FF78,其数据内容如下:

0012FF78: 61 CC CC CC FF FF FF FF

发现了什么?怎么中间夹杂了3个字节的CC?

看看MSDN上的说明:

When applied to a structure type or variable, sizeof returns the actual size, which may include padding bytes inserted for alignment.

原来如此,这就是传说中的字节对齐啊!一个重要的话题出现了。

为什么需要字节对齐?

计算机组成原理教导我们,这样有助于加快计算机的取数速度,否则就得多花指令周期了。

为此,编译器默认会对结构体进行处理(实际上其它地方的数据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上。以此类推,这样,两个数中间就可能需要加入填充字节,所以整个结构体的sizeof值就增长了。

让我们交换一下S1中char与int的位置:

struct S2
{
    int i;
    char c;
};

看看sizeof(S2)的结果为多少?怎么还是8。

再看看内存,原来成员c后面仍然有3个填充字节。

这又是为什么啊?别着急,下面总结规律。

    字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
    1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
    2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
    3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。

    对于上面的准则,有几点需要说明:
1) 前面不是说结构体成员的地址是其大小的整数倍,怎么又说到偏移量了呢?

因为有了第1点存在,所以我们就可以只考虑成员的偏移量,这样思考起来简单。想想为什么。

结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得,这个宏也在stddef.h中定义,如下:

#define offsetof(s,m) (size_t)&(((s *)0)->m)

例如,想要获得S2中c的偏移量,方法为

size_t pos = offsetof(S2, c);// pos等于4


2) 基本类型是指前面提到的像char、short、int、float、double这样的内置数据类型。这里所说的“数据宽度”就是指其sizeof的大小。由于结构体的成员可以是复合类型,比如另外一个结构体,所以在寻找最宽基本类型成员时,应当包括复合类型成员的子成员,而不是把复合成员看成是一个整体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。

这里叙述起来有点拗口,思考起来也有点挠头,还是让我们看看例子吧(具体数值仍以VC6为例,以后不再说明):

struct S3
{
    char c1;
    S1 s;
    char c2;
};

S1的最宽简单成员的类型为int,S3在考虑最宽简单类型成员时是将S1“打散”看的,所以S3的最宽简单类型为int。这样,通过S3定义的变量,其存储空间首地址需要被4整除,整个sizeof(S3)的值也应该被4整除。

c1的偏移量为0,s的偏移量呢?这时s是一个整体,它作为结构体变量也满足前面三个准则,所以其大小为8,偏移量为4,c1与s之间便需要3个填充字节,而c2与s之间就不需要了,所以c2的偏移量为12,算上c2的大小为13,13是不能被4整除的,这样末尾还得补上3个填充字节。最后得到sizeof(S3)的值为16。


    通过上面的叙述,我们可以得到一个公式:
    结构体的大小等于最后一个成员的偏移量加上其大小再加上末尾的填充字节数目,即:

sizeof( struct ) = offsetof( last item ) + sizeof( last item ) + sizeof( trailing padding )

 

10.类的sizeof
 
类的sizeof值等于类中成员变量所占用的内存字节数。如:
****************************************************************
 
class A
{
 public:
     int b;
     float c;
     char d;
};


int main(void)
{
  A object;
  cout << "sizeof(object) is " << sizeof(object) << endl;
  return 0 ;
}
 
***************************************************************

 
 
输出结果为12(我的机器上sizeof(float)值为4,字节对其前面已经讲过)。
 
不过需要注意的是,如果类中存在静态成员变量,结果又会是什么样子呢?
 
***************************************************************

class A
{
 public:
     static int a;
     int b;
     float c;
     char d;
};


int main()
{
  A object;
  cout << "sizeof(object) is " << sizeof(object) << endl;
  return 0 ;
}

 
**************************************************************
 
 
16?不对。结果仍然是12.


因为在程序编译期间,就已经为static变量在静态存储区域分配了内存空间,并且这块内存在程序的整个运行期间都存在。

而每次声明了类A的一个对象的时候,为该对象在堆上,根据对象的大小分配内存。

 
如果类A中包含成员函数,那么又会是怎样的情况呢?看下面的例子
 
*************************************************************

class A
{
 public:
     static int a;
     int b;
     float c;
     char d;
     int add(int x,int y)
     {
       return x+y;
     }
};

int main()
{
  A object;
  cout << "sizeof(object) is " << sizeof(object) << endl;
  b = object.add(3,4);
  cout << "sizeof(object) is " << sizeof(object) << endl;
  return 0 ;
}
 
***************************************************************
 
结果仍为12。
因为只有非静态类成员变量在新生成一个object的时候才需要自己的副本。
所以每个非静态成员变量在生成新object需要内存,而function是不需要的。
 
 注、sizeof与其他操作符的关系

  sizeof的优先级为2级,比/、%等3级运算符优先级高。它可以与其他操作符一起组成表达式。如i*sizeof(int);其中i为int类型变量。
注:C++中的多态和虚继承也是非常重要的东西,不过比较复杂,编译器不同,细节也有所不同。
1. What is an IDE (Integrated Development Environment), and what are its main components? 2. What is the role of a compiler in the C++ development process? 3. What is the difference between source code (e.g., a .cpp file) and an executable file? 4. In the "Hello, World!" program, what is the purpose of the line #include <iostream>? 5. What is special about the main() function in a C++ program? 6. Why do computers fundamentally operate using the binary (base-2) system? 7. What is the base of the hexadecimal system? Why is it often used by programmers as a shorthand for binary numbers? 8. Explain the "triad" method for converting an octal number to binary. 9. Briefly describe the "division by 2" method for converting a decimal number to binary. 10. What is the decimal value of the binary number 1011? 1. What is the purpose of the std::cout object? Which header file must be included to use it? 2.What is the difference between an escape sequence like \n and a manipulator like std::endl? (Hint: Both create a new line, but they have a subtle difference). 3.How would you print the following text to the console, including the quotes and the backslash: He said: "The file is in C:\Users\"? 4.Is it possible to write an entire multi-line text output using only one std::cout statement? If yes, how? 5.What is a syntax error? Give an example of a syntax error from Task 2. (Task 2: Debugging The following program contains several syntax errors. Copy the code into your IDE, identify the errors, fix them, and run the program to ensure it works correctly. Incorrect Code: */ Now you should not forget your glasses // #include <stream> int main { cout << "If this text" , cout >> " appears on your display, cout << " endl;" cout << 'you can pat yourself on ' << " the back!" << endl. return 0; "; ) Hint: Pay close attention to comments, header files, brackets ({}), operators (<<), semicolons, and how strings and manipulators are written.) 1. What is the difference between variable declaration and initialization? 2.What will be the result of the expression 7 / 2 in C++? Why? 3.What will be the result of the expression 10 % 3? What is the main purpose of the modulus operator? 4. What is the purpose of std::cin and the >> operator? 5. A beginner tries to swap two integer variables a and b with the code a = b; b = a;. Why will this not work correctly? 1. What is an algorithm? Name the primary ways to represent an algorithm. 2.List the main flowchart symbols and explain their purpose. 3.What are the three fundamental types of algorithm structures? Briefly describe each. 4.In a branching algorithm, what determines the flow of execution? 5.What is the key characteristic of a linear algorithm? 6.When is a cyclic algorithm structure used?7. 8. 9. 7.Explain the purpose of a connector in a flowchart. 8.What is the difference between a predefined process block and a standard process block? 9.In the context of solving a quadratic equation algorithm, what condition must be checked before calculating the roots? Why? 1. What are the three main approaches to data input and output offered by C++? 2. What is the purpose of the SetConsoleOutputCP(65001) and SetConsoleCP(65001)
functions in the provided C++ program example? 3. Explain the difference between the cin and cout objects in Stream 1/0. 4. When using formatted 1/0, which header file must be included to use manipulators like setw and setprecision? 5. List three manipulators used for data output in C++ and briefly describe what each one does. 6. In Formatted I/0 using printf), what are the conversion specifications for a decimal integer and a real number in exponential form? 7. What is the difference in how the & (address-of) operator is used when inputting a value for an integer variable versus a string variable using the scanf() function? 8. Which Character I/O function is used to output a single character to the screen, and which is used to output a string? 9. Describe the syntax and function of the ternary operator in C++. 10. What is the difference between the logical AND (&&) and logical OR (I|) operators when combining multiple conditions? 11. When is the default label executed in a C++ switch statement? 12. What is the primary purpose of the break statement within a switch block? 1. What is the main purpose of using loops in programming? 2. Explain the key difference between the for, while, and do while loops. 3. What happens if you forget to include the increment/decrement statement in a while loop? 4. How can you interrupt an infinite loop during program execution? 5. What is the role of the setw() and setfill) manipulators in C++? 6. In a nested loop, how does the inner loop behave relative to the outer loop? 7. What is type casting, and why is it used in loop calculations? 8. How does the do while loop differ from the while loop in terms of condition checking? 9. What output formatting options can be used to align numerical results in columns? 10*. How would you modify a loop to skip certain iterations based on a condition? 1. List the six main biwise operators in C++ and explain the function of each. 2. Why cannot bitwise operations be applied to variables of floating-point type? 3. Explain the purpose of the << (left shift) and >> (right shift) operators. What is the typical effect on the decimal value of a number when it is shifted left by 1? Shifted right by 1? 4. Describe the process of using a mask to check the value of a specific bit within an
integer. 5. How can you use the bitwise AND operator (&) to check if a number is even or odd?
Explain the logic. 6. What is the difference between the logical AND (&&) and the bitwise AND (&)? Provide an example scenario for each. 7. Explain the purpose of the ~ (bitwise NOT) operator. What is the result of applying it to a mask, and how can this be useful? 1. What is the primary goal of program debugging? What types of errors can it help identify? 2. Describe the difference between Step Over (F10) and Step Into (F11) debugging commands. When would you choose one over the other? 3. What is the purpose of a breakpoint in planned debugging? How do you set and remove a breakpoint in Visual Studio? 4. Explain the utility of the "Watch" window compared to the "Autos" or "Locals" windows during a debugging session. 5. What is the key difference between the Debug and Release configurations when building a project? Why is it necessary to create a Release version after successful debugging? 6. List at least three types of files commonly found in a project's Debug folder and briefly state their purpose (e.g., *.pdb). 7. During debugging, you notice a variable has an incorrect value. How can you change its value during runtime to test a hypothesis without modifying the source code? 8. What command is used to exit the debug mode and stop the current debugging session? 1. What is an array in C++? List its three main characteristics. 2. How are array elements numbered in C++? What is the valid index range for an array declared as int data[25];? 3. Explain the difference between array declaration and initialization. Provide an example of each. 4. What is an initializer list? What happens if the initializer list is shorter than the array size? 5. How can you let the compiler automatically determine the size of an array during initialization? 6. What values do elements of a local array contain if it is declared but not explicitly initialized? How does this differ from a global array? 7. What is an array out-of-bounds error? Why is it dangerous, and what are its potential consequences? 8. How do you calculate the number of elements in an array using the sizeof operator?
Provide the formula. What is a significant limitation of this method? 9. Why is it impossible to copy the contents of one array into another using the assignment
operator (arrayB = arrayA;)? What is the correct way to perform this operation? 10. Why does comparing two arrays using the equality operator (arrayA == arrayB) not check if their elements are equal? How should array comparison be done correctly? 11. What does the name of an array represent in terms of memory? 1. What is a pointer in C++ and what are its two main attributes? 2. Explain the difference between the & and * operators when working with pointers. 3. Why is pointer initialization critical and what dangers do uninitialized pointers pose? 4. What is the fundamental relationship between arrays and pointers in C++? 5. How does pointer arithmetic work and why does ptr + 1 advance by the size of the pointed type rather than 1 byte? 6. What is the difference between an array name and a pointer variable? Why can't you increment an array name? 7. What are the differences between const int*, int* const, and const int* const? 8. How can you safely iterate through an array using pointers, and what are the boundary risks? 9. What is a null pointer and why should you check for nullptr before dereferencing? 10. How do you access array elements using pointer syntax, and how does the compiler translate arr[i] internally? 1. What is a multidimensional array? How is a two-dimensional array structured in memory? 2. Explain the concept of an "array of arrays". How does this relate to the declaration int arr/ROWS//COLS;? 3. The name of a two-dimensional array without indices is a pointer constant. What does this pointer point to? What do the expressions *(A + i) and *(*(A + i) +j) mean for a two-dimensional array A? 4. Describe the different ways to access the element A/1/[2/ of a two-dimensional array
using pointers. 5. What is the rule for omitting the size of dimensions when initializing and when passing a multidimensional array to a function? Why is it allowed to omit only the first dimension? 6. Explain the principle of "row-major order" for storing two-dimensional arrays in memory.
How does this affect element access? 7. Why are nested loops the standard tool for processing multidimensional arrays?
Describe the typical pattern for iterating through a matrix. 1. How is a character string stored in memory in C++? What is the role of the null terminator (10), and why is it critical for C-style strings? 2. Why must the size of a char array declared to hold a string be at least one greater than the number of characters you intend to store? 3. The array name without an index is a pointer constant. What does the name of a char array point to? 4. What are the two main ways to initialize a C-style string? What is a common mistake when using the initializer list method, and what is its consequence? 5. Why is it necessary to add _CRT_SECURE_NO_WARNINGS to the preprocessor definitions in Visual Studio when working with many standard C library functions?
What is the alternative approach? 6. What is the key difference between stropy and strncpy? Why might strncpy be considered safer? 7. How does the stremp function determine if one string is "less than" another? Why can't you use the == operator to compare two C-style strings for content equality? 8. Describe the purpose and parameters of the strok function. How do you get all tokens from a string? 9. What do the functions strchr and strrchr do? How do they differ? 10. Explain what the strstr function returns and what it is commonly used for. 11. What is the purpose of the functions in the < cctype> header? Give three examples of such functions and their use. 12. What is the difference between tolower(c) and_tolower(c)? When should you use each? 1. What is a function in C++? Name the three core benefits of using functions in a program. 2. What is the difference between a function declaration (prototype) and a function definition? Provide examples. 3. What is a function signature? Which elements are part of the signature, and which are not? 4. What methods of passing parameters to a function do you know? Explain the difference between pass-by-value, pass-by-pointer, and pass-by-reference. 5. Why can't you pass an array to a function by value? What is the correct way to pass an array to a function? 6. What is variable scope? How is it related to functions? 7. How does a function return a value? What happens if a function with a non-void return type does not return a value on all control paths? 8. Can you use multiple return statements in a single function? Provide an example. 9. What is function overloading? What is it based on? 10. How is interaction between functions organized in a program? Provide an example program with several functions. 11. What are default parameters? How are they specified, and in what cases are they useful? 12. How can you prevent a function from modifying the data passed to it? What modifiers are used for this? 13. What is recursion? Provide an example of a recursive function. 14. What common errors occur when working with functions? How can they be avoided? 15. How do you use pointers to functions? Provide an example of declaring and calling a function through a pointer. 用中文回答
11-18
删除链表中指定结点 【问题描述】输入链表 a,链表结点中包含学号、姓名,学号输入 -1,姓名随意代表一个链表输入结束。再输入待删除结点的学号 num,请编写删除链表中结点函数,从结点中删除学号为 num 的结点,并依次输出删除后的链表。若链表中不包含学号为 num 的结点,则先输出 no data,再依次输出链表结点。  【输入形式】输入链表 a 的数据和待删除结点的学号 num。其中,学号输入 -1,姓名随意代表一个链表输入结束。  【输出形式】输出删除后的新链表。  【样例输入】  101 Wang  102 Li  105 Zhang  106 Wei  -1 x  105  【样例输出】  101 Wang 102 Li 106 Wei    【样例输入】  101 Wang  102 Li  105 Zhang  106 Wei  -1 x  103  【样例输出】  no data 101 Wang 102 Li 105 Zhang 106 Wei #include <stdio.h> #include <stdlib.h> #include <string.h> #define LEN sizeof(NODE)  //用 typedef 将结构体改名字 typedef struct node { int num; char name[20]; struct node* next; } NODE;   NODE *Create_LinkList(); //读入学号,并删除指定学号的结点, //成功删除返回正数,未找到学号返回负数。 int Delete_LinkList(NODE *head); void Display_LinkList(NODE *head,int flag); void Free_LinkList(NODE *head);  int main() { NODE *head = NULL; int flag;  head = Create_LinkList(); flag=Delete_LinkList(head); Display_LinkList(head,flag); Free_LinkList(head);  return 0; }      void Display_LinkList(NODE *head,int flag) { NODE *p; if(flag<0) printf("no data "); for (p = head->next; p != NULL; p = p->next) printf ("%d %s ", p->num,p->name); }  void Free_LinkList(NODE *head) { NODE *p, *q; p = head; while (p->next != NULL) { q = p->next; p->next = q->next; free (q); } free (head); }
最新发布
11-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值