在尝试从源代码Linux内核Definition of container_of理解 container_of()的功能时,我发现宏定义的以下行似乎无所事事。
const typeof((((type *)0)-> member)* __ mptr =(ptr); \
因此,我编写了一个不带上述行的简单C程序,并尝试比较所获得的结果。 基本上,我试图理解新的实现 my_contianer_of()与 container_of() 有何不同?
public class MainActivity extends AppCompatActivity {
LinearLayout verticallayout,horizontalLayout; //got
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
verticallayout = findViewById(R.id.verticalLayout); //got
}
public void createRow(View view){
createRow(); //got
}
private void createRow() { //got
horizontalLayout = new LinearLayout(this);
LinearLayout.LayoutParams horizontalParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
horizontalLayout.setOrientation(LinearLayout.HORIZONTAL);
horizontalParams.setMargins(15, 5, 15, 5); // LEFT, TOP, RIGHT, BOTTOM
horizontalLayout.setLayoutParams(horizontalParams);
createSpinner();
createCheckbox();
createEditText();
verticallayout.addView(horizontalLayout, horizontalParams);
}
private void createEditText() {
EditText editText = new EditText(this);
LinearLayout.LayoutParams editParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
editParams.setMargins(10, 10, 10, 10);
editText.setLayoutParams(editParams);
horizontalLayout.addView(editText);
}
private void createCheckbox() { //done
CheckBox checkBox = new CheckBox(this);
LinearLayout.LayoutParams checkParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
checkParams.setMargins(10, 10, 10, 10);
checkParams.gravity = Gravity.LEFT;
checkBox.setLayoutParams(checkParams);
horizontalLayout.addView(checkBox);
}
private void createSpinner() {
Spinner spinner = new Spinner(this);
//ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_dropdown_item, spinnerArray);
//spinner.setAdapter(spinnerArrayAdapter);
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
spinnerParams.setMargins(10, 10, 10, 10);
spinnerParams.gravity = Gravity.LEFT;
spinner.setLayoutParams(spinnerParams);
horizontalLayout.addView(spinner);
}
}
以下是上述c程序的示例输出。
#include <stdio.h>
#include <stddef.h>
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define my_container_of(ptr, type, member) ({ \
(char *)ptr - offsetof(type, member);})
struct container {
int *i;
char c;
float f;
};
void foo(char *cptr)
{
printf("foo : %p\n", my_container_of(cptr, struct container, c));
}
int main(int argc, char *argv[])
{
struct container tc;
printf("&tc : %p\n", &tc);
printf("cof : %p\n", container_of(&tc.c, struct container, c));
printf("mycof: %p\n", my_container_of(&tc.c, struct container, c));
foo(&tc.c);
return 0;
}
请不要将此问题标记为任何其他问题或此Understanding container_of macro in the linux kernel的重复,因为这些问题没有为我的查询提供所需的答案。
答案 0 :(得分:2)
您的实现类型不安全。它不能确保您传递的指针与该成员具有相同的类型,这可能会导致错误。因此,例如:
my_container_of(&tc.f, struct container, c)
编译就可以了。内核版本至少会发出有关不兼容的指针类型的警告。还是完全清除,导致编译停止,具体取决于您的GCC标志。
自然地,内核版本不能防止所有错误(例如,如果f
和c
属于同一类型)。但这是可以捕获的,应该捕获。