我有一个问题,似乎无法解决。我希望有人能够向我全面解释。我了解到它非常基本。
问题如下:
以下变量如何进入连续的内存地址及其值?
int8_t a = 0x65;
char b = 'k';
uint16_t c = 22222;
例如,
int8_t esim = 9;
将存储为
0000:00001001
有人吗?
答案 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 个字节的形式存储在内存中-0b11001110
和0b01010110
在递增的内存地址处(小尾数,通常),或相同的2个字节相反:0b01010110
和0b11001110
(大端)。b
,如果 执行字符集是ASCII兼容的,因为存在int8_t
,则char
必须也为8位宽,则其值将存储为0b01101011
(即107,k
的ASCII码)。此外,uint16_t
对象的对齐要求通常是2;如果是这种情况,则必须从偶数地址开始。
这种推论是唯一可能的,因为int8_t
和uint16_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
的内存地址的相对地址。
再次:不要以为平台上一定是这种情况。