×

Loading...
Ad by
  • 推荐 OXIO 加拿大高速网络,最低月费仅$40. 使用推荐码 RCR37MB 可获得一个月的免费服务
Ad by
  • 推荐 OXIO 加拿大高速网络,最低月费仅$40. 使用推荐码 RCR37MB 可获得一个月的免费服务

my sample code, thanks for you attention.

#include <stdio.h>

struct s{
char c;
int a;
long l;
};

struct s *get_s_ptr(int *a_ptr)
{
struct s r;
return (struct s *)((unsigned long)a_ptr - ((unsigned long)&r.a - (unsigned long)&r));

}

main()
{
struct s r, *r_ptr;

r.c = 'A';
r.a = 10;
r.l = 123456789;

printf("r.c=%c r.a=%d r.l=%ld\n", r.c, r.a, r.l);
r_ptr = get_s_ptr(&r.a);
printf("r_ptr->c=%c r_ptr->a=%d r_ptr->l=%ld\n", r_ptr->c, r_ptr->a, r_ptr->l);
}
Report

Replies, comments and Discussions:

  • 工作学习 / 专业技术讨论 / 一个c语言的考题看不明白, 那位帮忙解释解释? 谢谢. (考题原文见内)
    Given a pointer to member a within a struct, write a routine that returns a pointer to the struct.

    struct s
    {
    ...
    int a;

    };

    struct s *get_s_ptr(int *a_ptr)
    {









    }
    • The key is the offset of a in s ==> s = a - offset
      • seems we have the same way to understand the question. now the problem is: how to know the offset?
        • 在函数里建一个s的实例r,用r.a的地址减r的地址就是offset.这样理解对吗?
          • 应该有 macros 可以做这个的吧。不行再在 function 里建 instance,只是要设计好一点,重用结果,而不是an instance per call。不用C十几年了,不知道对不对。
            • my sample code, thanks for you attention.
              #include <stdio.h>

              struct s{
              char c;
              int a;
              long l;
              };

              struct s *get_s_ptr(int *a_ptr)
              {
              struct s r;
              return (struct s *)((unsigned long)a_ptr - ((unsigned long)&r.a - (unsigned long)&r));

              }

              main()
              {
              struct s r, *r_ptr;

              r.c = 'A';
              r.a = 10;
              r.l = 123456789;

              printf("r.c=%c r.a=%d r.l=%ld\n", r.c, r.a, r.l);
              r_ptr = get_s_ptr(&r.a);
              printf("r_ptr->c=%c r_ptr->a=%d r_ptr->l=%ld\n", r_ptr->c, r_ptr->a, r_ptr->l);
              }
              • 加减instance的地址?还是用sizeof算offset?
                • result of sizeof() has no meaning to the offset
                  • structure should have a continuous memery chunk. You got a pointer pointing to somewhere in the middle of an instance in the momory. should you use the given pointer minus sizeof() whatever variables
                    which are allocated in front of the given pointer?

                    just don't understand why you want to involve a whatever instance.
                    • 不一定。可能有对其的问题,页就是会有空穴。
              • 有一个宏offsetof可以直接用,你这个也算可以但是到64位上就不行了。
              • return (struct s *)( (char *)a_ptr - ((cha *)&r - (char *)&r.a);
                • 打漏个字符 return (struct s *)( (char *)a_ptr - ((cha *)&r - (char *)&r.a);
                  • 反了:return (struct s *)( (char *)a_ptr - ((cha *)&r.a - (char *)&r);
    • return (struct s *) ( (int)(a_ptr) - (int) ( &(( (struct s * )( 0 ) )->a ) ) );
      • 这个64位也不行,最好是用(BYTE*)(a_ptr)代替(int)(a_ptr)。不过还是用offsetof宏好,让面试的人可以抖个包袱,问你不用这个宏怎么实现,呵呵。
        • 那也是long long,而不是byte *, 另外用MACRO的话就不这么用了。LISTOFFSET本质上也是把0转化成结构指针,再去值,得到offset.
          • longlong也可以,不分32、64总是64位。byte*在32位os上是32反之是64位的。你得到offset的方法没问题,记得microsoft的宏offsetof就是这么定义的。用offsetof宏的话,大概就是(struct×)((byte*)(a_ptr) - offsetof(struct s, a));
            • 我说的意思是如果要用macro,就无需这个什么函数了,直接 #define BASE_ADDR(ADDR, TYPE, MEMB) ( (TYPE *) ( ADDR - ((size_t) &((TYPE *)0)->MEMB) ) 的了。
              • offsetof是已经定义好的标准宏,不是用户定义的宏.
              • fix bug: #define BASE_ADDR(ADDR, TYPE, MEMB) ( (TYPE *) ( ADDR - ((size_t) &((TYPE *)0)->MEMB) ) ==>> #define BASE_ADDR( ADDR, TYPE, MEMB) ( (TYPE *) ( (char *)ADDR - ((size_t) &((TYPE *)0)->MEMB) )
            • P.S offsetof属于C99范畴,不是所有compiler都支持。
              • 有可能,我没查过。不过比较新的gcc,microsoft编译器都支持。
    • I don't know how to do that, but my question is why having this function in design? If this is needed, why not create the struct as a class and simply implement a member function to return class pointer?
      • As the title says, it's C not C++.
        • what about this
          struct s
          {
          ...
          int a;

          };

          struct s *get_s_ptr(int *a_ptr)
          {
          s m_s;
          void *p_s = null, *p_a = null;
          int offset;

          p_s = &m_s;
          p_a = &(m_s.a);

          offset = p_a - p_s;
          return (a_ptr - offset);
          }
          • I like this one!
    • This is the MACRO used in the well-known Apache web server. it works for me on a IA64 box.
      #define APR_OFFSET (p_type, field ) ((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))