`
Uranus
  • 浏览: 48964 次
  • 来自: sh
最近访客 更多访客>>
社区版块
存档分类
最新评论

返回内部静态成员 熟练C/C++(一)

阅读更多
 

        看完陈皓的C/C++返回内部静态成员的陷阱,认识到自己确实对C/C++本身语法研究的不够清楚,所以这些时间就在对基本知识进行回顾,真的还蛮有意思的。

        我在用C/C++函数时,从没有全面考虑过该函数功能,只是知道它能做,基本对函数细节没有了解,就拿下面这个函数做个例子:

        char *inet_ntoa(struct in_addr in);

        struct in_addr {      unsigned long int s_addr; }

 

        看到这个我就能想到该函数是把一个unsigned long type的数转换成一个字符串。其它什么都不想。现在让我们来仔细品读里面的东西。

        我传入一个unsigned long type的数据,它给我传出一个char *,那这个char * 在函数里怎么分配空间的。首先不可能是堆分配,因为如果是那样的话,你用完这个函数后还要释放资源。其次不可能是栈分配,因为那样函数返回后栈也会跟着释放。那还有可能是全局变量,如果这样的话,C/C++中已经有好多全局了。那还有一种是static的可能,static不会随着函数的返回而释放,也就是说,它是一块长期被分配的内存空间,现在在假若我在程序中这样写:

        printf(“%s, %s”, inet_ntoa(a), inet_ntoa(b)); //a, b 是两个不相等的值

        输出会让我大吃一惊,输出结果一样。原因很简单,就是printf先求b,把值给了那个static,然后再求a, 把值又给了staticstatic的那块内存最终被写入了a的值,这个时候输出,那当然就输出的同一个值了。还有一种错误写法,如下:

 

        Char *tmp1 = inet_ntoa(a);

        Char *tmp2 = inet_ntoa(b);

        这样也是有问题的,因为tmp1tmp2都指向了一块内存,当前的static的值就是b的值了。所以总结如下,使用这种函数一定要copy函数返回的值,而不能去保存其内存地址!
附inet_ntoa()源码:
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <bits/libc-lock.h>

/* The interface of this function is completely stupid, it requires a
   static buffer.  We relax this a bit in that we allow at least one
   buffer for each thread.  */


/* This is the key for the thread specific memory.  */
static __libc_key_t key;

/* If nonzero the key allocation failed and we should better use a
   static buffer than fail.  */

static char local_buf[18];
static char *static_buf;                                //静态

/* Destructor for the thread-specific data.  */
static void init (void);
static void free_key_mem (void *mem);


char *
inet_ntoa (struct in_addr in)
{
  __libc_once_define (static, once);
  char *buffer;
  unsigned char *bytes;

  /* If we have not yet initialized the buffer do it now.  */
  __libc_once (once, init);

  if (static_buf != NULL)
    buffer = static_buf;
  else
    {
      /* We don't use the static buffer and so we have a key.  Use it
to get the thread-specific buffer.  */

      buffer = __libc_getspecific (key);
      if (buffer == NULL)
{
  /* No buffer allocated so far.  */
  buffer = malloc (18);
  if (buffer == NULL)
    /* No more memory available.  We use the static buffer.  */
    buffer = local_buf;
  else
    __libc_setspecific (key, buffer);
}
    }

  bytes = (unsigned char *) &in;
  __snprintf (buffer, 18, "%d.%d.%d.%d",
      bytes[0], bytes[1], bytes[2], bytes[3]);

  return buffer;
}


/* Initialize buffer.  */
static void
init (void)
{
  if (__libc_key_create (&key, free_key_mem))
    /* Creating the key failed.  This means something really went
       wrong.  In any case use a static buffer which is better than
       nothing.  */

    static_buf = local_buf;
}



攀升 2007-04-13 16:07 发表评论
分享到:
评论

相关推荐

    c/c++面试笔试题目深度解析

    在C/C++面试和笔试中,常常会遇到各种各样的问题,这有助于考察...理解并熟练应用这些概念是成为一名优秀的C/C++开发者的基础。在面试中,能够清晰地解释这些问题的解决方案和背后的原理,将大大提升候选人的专业形象。

    c/c++ 学习总结 初学者必备

    在C/C++编程语言中,变量的定义和声明是非常基础但至关重要的概念。...以上是C/C++学习中的一些关键知识点,这些基础知识对于初学者来说是必不可少的,理解和掌握它们是成为熟练的C/C++程序员的基础。

    cpp/c++入门常用的语法

    C++是一门强大的编程语言,它以其丰富的语法特性、面向对象的设计理念以及高度的灵活性而受到...理解并熟练运用这些基础知识,是成为一名合格的C++程序员的必备条件。在实践中不断探索和学习,才能更好地驾驭这门语言。

    C、C++函数辞典.chm

    C++中的函数可以分为普通函数、成员函数、友元函数、重载函数、模板函数、静态成员函数等。其中,成员函数是类的一部分,如构造函数和析构函数,用于对象的创建和销毁;友元函数可以访问类的私有和保护成员;重载...

    c++ demo,运算符索引重载,成员函数的实现

    在C++编程语言中,运算符重载是其特性之一,允许我们为现有的运算符赋予新的含义,以便在自定义类型上使用。本教程将深入探讨如何在C++中实现运算符索引重载...理解并熟练掌握这一技巧,对于提升C++编程能力至关重要。

    C++模拟题5答案.docx

    静态成员函数不能访问非静态成员C. 静态成员可以在类的外部定义D. 静态数据成员需要在类的外部进行初始化答案:ABCD解析:(P107)静态成员属于类,而非类的实例,它们在内存中只有一份拷贝;静态成员函数没有this...

    c++语言程序设计课件_C语言教程_C++程序设计--类与对象_

    此外,你还将了解到访问控制(public、private和protected)、友元函数、静态成员、虚函数等概念,这些都是C++面向对象编程的重要组成部分。 理解并掌握这些知识点,不仅能够帮助你编写出高效、可维护的C++代码,还...

    从 C 转向 C++

    从C语言转向C++的过程中,对于已经熟练掌握C语言的程序员来说确实是一个不小的挑战。由于C是C++的一个子集,这意味着C中的所有特性在C++中都可以继续使用。然而,在C++中提供了更多高级的功能与概念,使得程序员在...

    C++笔试题目带答案.docx

    示例中的`GetPI()`函数是静态成员函数,返回一个常数值。 - `Constants constants;`创建了类`Constants`的一个全局实例,其`GetPI()`方法可以被调用。 6. 内存管理: - `malloc()`是C/C++中的动态内存分配函数,`...

    C++总结.docx

    静态成员函数只能访问静态成员,若要访问非静态成员,可以通过传递对象作为参数来实现。 总结起来,C++不仅仅是C语言的扩展,它引入了面向对象编程的概念,增强了类型检查和内存管理,并提供了丰富的特性和工具来...

    C++考试题(选择题).docx

    C++是一种强大的面向对象的编程语言,它在C语言的基础上增加了许多高级特性和概念,使得程序员能够更好地组织和管理代码。以下是从给定文件中提取的一些C++知识点: 1. **静态函数**:静态成员函数属于类而不属于类...

    C++习题 老师给的.docx

    静态成员变量(如`C::sum`, `C::count`, `Student::sum`, `Student::count`, `B::b`)是属于类而不是类的实例的。这意味着它们在所有类的实例之间共享同一份存储,可以通过类名直接访问,如`B::Getb()`。 5. 指针...

    详细手册13010

    **C和C++函数用法详细手册** C和C++是两种非常重要的编程语言,它们在计算机科学领域中有着广泛的应用。C语言以其简洁、高效和底层特性深受程序员...在实践中不断应用和巩固,将有助于你成长为一名熟练的C/C++程序员。

    C++习题.docx

    在C++中,静态成员变量像全局变量一样在整个程序中只有一个实例,不受对象生命周期的影响。因此,`static sample c;`在类外定义了一个静态成员,程序会先构造这个静态成员。在给出的代码中,`c`在main函数调用`fn`...

    C++期末考试题及答案(精编版).pdf

    C++是一种广泛使用的编程语言,它是C语言的扩展,增加了面向对象编程的特性。下面将对C++的一些关键概念和语法进行详细解释。 1. **C++与C的关系**: - C语言是C++的基础,C++包含了C语言的所有语法,因此C语言...

    C++ 函数 英文版+中文版

    在编程世界中,C++是一种强大且广泛应用的...总的来说,理解并熟练运用C++中的函数是成为一名优秀的C++程序员的关键步骤。通过深入研究这些概念,结合实际编程练习,你将能够更好地利用函数来构建高效、可维护的程序。

    C++中的一些问题

    3. 在类的外部,`static`可以用来声明类的静态成员函数,这些函数不与任何特定的类实例关联,可以直接通过类名调用,无需对象实例。例如:`static void printMessage();` 总结起来,`const`和`static`在C++中扮演着...

    C@C++复习--草稿1

    作用域决定变量的可见范围,静态成员在所有对象间共享,常成员是不可变的。友元(friend)允许非成员函数或类访问私有或保护成员,打破了封装。 第12章:继承和派生 继承允许创建新的类(派生类)基于现有类(基类)...

Global site tag (gtag.js) - Google Analytics