C内存地址和值

时间:2018-10-12 14:53:25

标签: c

我有一个问题,似乎无法解决。我希望有人能够向我全面解释。我了解到它非常基本。

问题如下:

以下变量如何进入连续的内存地址及其值?

int8_t a = 0x65;
char b = 'k';
uint16_t c = 22222;

例如,

int8_t esim = 9;

将存储为

0000:00001001

有人吗?

2 个答案:

答案 0 :(得分:10)

  

我有一个问题,似乎无法解决。我希望有人能够向我全面解释。我了解到它非常基础。

在这里你错了。 非常基础的,但并不像您认为的那样

  • 不同的变量不必存储在内存中的连续位置。 (或者正如最后一个项目符号所说,根本不存储在内存中)

  • 多字节值中单个字节的存储是实现定义的-请查看编译器手册。但是,当今大多数个人计算处理器对整数使用小尾数2补码。

  • 即使编译器将它们 组织为以与声明时完全相同的顺序出现在内存中,每种数据类型也可能需要特定于实现的对齐方式,因此只能从以下位置开始该对齐方式的倍数的地址

  • 最后,根本不需要任何变量或内存分配,编译器只需要生成一个行为为as if的程序即可。


但是,我们可以肯定说一些有关您的程序的信息。如果摘录

#include <stdint.h>

int8_t a = 0x65;
char b = 'k';
uint16_t c = 22222;

编译并将变量放入内存,然后

  • a将是8位,值为0b01100101
  • c将为16位,并以 2 个字节的形式存储在内存中-0b110011100b01010110在递增的内存地址处(小尾数,通常),或相同的2个字节相反:0b010101100b11001110(大端)。
  • 对于b如果 执行字符集是ASCII兼容的,因为存在int8_t,则char必须也为8位宽,则其值将存储为0b01101011(即107,k的ASCII码)。

此外,uint16_t对象的对齐要求通常是2;如果是这种情况,则必须从偶数地址开始。

这种推论是唯一可能的,因为int8_tuint16_t 必须没有填充位,因此,有了它们,我们可以推断出最小可寻址单元的宽度( char)也必须是8位。并且uint16_t只有2个字节,因此对于字节序只能有两个选择。


测试GCC如何组织全局变量很容易。考虑具有源代码的模块

#include <stdint.h>
int8_t a = 0x65;
char b = 'k';
uint16_t c = 22222;

我们可以将其编译为目标文件:

% gcc -c layouttest.c -o layouttest.o

,然后使用nm列出符号及其地址:

% nm layouttest.o            
0000000000000000 D a
0000000000000001 D b
0000000000000002 D c

这似乎是Jabberwocky的答案所期望的。如果现在使用-O3进行编译,则结果可能会不同:

% gcc -c layouttest.c -o layouttest.o -O3; nm layouttest.o
0000000000000003 D a
0000000000000002 D b
0000000000000000 D c

即变量被重新组织,c位于底部。

答案 1 :(得分:2)

对Antti Haapala的回答的补充:

虽然完全由编译器决定如何以及在何处存储变量,但是连续声明的变量的内存布局通常与声明的顺序相同,尤其是在非优化代码中。

所以变量声明如下:

    public static final String urlKey = "urlKey";
    public static final String ImageKey = "imageKey";
    private final List<Article> articleList;
    Context context;
    private ClipboardManager myClipboard;
    private ClipData myClip;

    public NewsAdapter(List<Article> articleList) {

        this.articleList = articleList;

    }


    @NonNull
    @Override
    public NewsViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View itemView = LayoutInflater.
                from(viewGroup.getContext()).
                inflate(R.layout.news_item, viewGroup, false);
        return new NewsViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull final NewsViewHolder newsViewHolder, final int i) {
        final Article article = articleList.get(i);
        SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");

        Date d = new Date();
        try {
            d = input.parse(article.getPublishedAt());
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (java.text.ParseException e) {
            e.printStackTrace();
        }


        String formatted = output.format(d);

        newsViewHolder.articleAuthor.setText(article.getAuthor());
        newsViewHolder.articleTitle.setText(article.getTitle());
        newsViewHolder.articleDescription.setText(article.getDescription());
        newsViewHolder.articleDate.setText(formatted);
        //newsViewHolder.articleDate.setText(article.getPublishedAt());
        Picasso.get().load(article.getUrlToImage()).into(newsViewHolder.articleImage);
        newsViewHolder.copy_Button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {


                myClipboard = (ClipboardManager) v.getContext().getSystemService(Context.CLIPBOARD_SERVICE);


                myClip = ClipData.newPlainText("label", newsViewHolder.articleTitle.getText().toString());
                myClipboard.setPrimaryClip(myClip);
                Toast.makeText(v.getContext(), "Copied to clipboard", Toast.LENGTH_SHORT).show();

            }
        });
        newsViewHolder.shareButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
                sharingIntent.setType("text/plain");
                String articleDescription = article.getDescription();
                String articleTitle = article.getTitle();
                sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, articleDescription);
                sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, articleTitle);
                v.getContext().startActivity((Intent.createChooser(sharingIntent, "Share using")));
            }
        });
        newsViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(view.getContext(), DetailActivity.class);
//start the activity from the view/context

                intent.putExtra("urlKey", article.getUrl());
                //intent.putExtra("imageKey", article.getUrlToImage());
                view.getContext().startActivity(intent);
            }
        });

    }


    @Override
    public int getItemCount() {

        return articleList.size();
    }


    public final class NewsViewHolder extends RecyclerView.ViewHolder {
        // TextView articleAuthor, articleTitle, articleDescription, articleUrl;
        //  ImageView articleImage;

        @BindView(R.id.article_Image)
        ImageView articleImage;
        @BindView(R.id.article_Author)
        TextView articleAuthor;
        @BindView(R.id.article_Title)
        TextView articleTitle;

        @BindView(R.id.article_Description)
        TextView articleDescription;
        @BindView(R.id.article_Date)
        TextView articleDate;
        @BindView(R.id.share_button)
        ImageButton shareButton;
        @BindView(R.id.copy_Button)
        ImageButton copy_Button;


        public NewsViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);

            if (context != null) {
                Typeface typeface = ResourcesCompat.getFont(context, R.font.roboto_black);
                articleTitle.setTypeface(typeface);

            }

        }

    }
}

可以这样存储:

int8_t a = 0x65;
char b = 'k';
uint16_t c = 22222;

其中Address Content in binary -------------------------- 0000: 01010101 (0x64) 0001: 01101011 ('k' = 107, ASCII code of k) 0002: 11001110 (low bits of 22222) 0003: 01010110 (high bits of 22222) 是相对于变量Address的内存地址的相对地址。

再次:不要以为平台上一定是这种情况。