Can lldb display char * / strings in structs more efficiently? - lldb

lldb has a habit to show me strings in a very spread out manner, which is a little annoying but not a show stopper. But maybe someone already knows how to make it a bit more efficient with its display size:
Example:
(lldb) p *tq
(taskq_t) $14 = {
tq_name = {
[0] = 's'
[1] = 'y'
[2] = 's'
[3] = 't'
[4] = 'e'
[5] = 'm'
[6] = '_'
[7] = 't'
[8] = 'a'
[9] = 's'
[10] = 'k'
[11] = 'q'
[12] = '\0'
[13] = '\0'
[14] = '\0'
[15] = '\0'
[16] = '\0'
[17] = '\0'
[18] = '\0'
[19] = '\0'
[20] = '\0'
[21] = '\0'
[22] = '\0'
[23] = '\0'
[24] = '\0'
[25] = '\0'
[26] = '\0'
[27] = '\0'
[28] = '\0'
[29] = '\0'
[30] = '\0'
[31] = '\0'
}
tq_lock = {
Would prefer:
(lldb) p *tq
(taskq_t) $14 = {
tq_name = {
"system_taskq\0"
}
tq_lock = {
Or similar - as in, a string. As it gets quite long when it is char path[MAXPATH].

Showing all the elements is the natural view for an array, and since there's no guarantee that a char array is actually a null terminated string, even printing char arrays as an array is a reasonable default. But as you observe, if you know the array holds a null terminated string you really do want to print it more compactly.
Fortunately, lldb has a system for providing "alternate" views of data objects. That's why, for instance you see:
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100003f0b has_char`main at has_char.c:8
5 {
6 char *myStr = "some string here";
7 char myArr[20] = {'s', 'o', 'm', 'e', ' ', 's', 0};
-> 8 return strlen(myStr) + strlen(myArr);
^
9 }
Target 0: (has_char) stopped.
(lldb) v myArr
(char [20]) myArr = "some s"
By default lldb presents char[NN] arrays as null terminated strings.
That's done using lldb's "summary formatters". There's a bunch more information about them here:
https://lldb.llvm.org/use/variable.html
You can find out how a particular variable gets its formatting, which is sometimes useful when you're looking for something to copy, with:
(lldb) type summary info myArr
summary applied to (char [20]) myArr is: `${var%s}` (hide value) (skip pointers)
The summaries are registered by a type name or type regular expression, and then applied to any value of that type when printing it. They also follow typedef chains so the same summary will be provided for variables whose type is a typedef of a registered type. What is the type of tq_name, it looks like it is just a char array? I'm a little surprised you had to do anything here...
Anyway, no worries, you can always add one explicitly for your type.
The command for that is:
(lldb) type summary add -s ${var%s} -p -v TypeNameOfTQ
-s is the summary string, see the docs cited above for more on that.
-p because you don't want to format a char [10]* this way.
-v because you explicitly don't want to see the elements one by one - which is the natural value of the array.

Related

Ask about char in array

example
char names[2][5] = {"john","boy"};
I want to ask about char 2 dimension array in c, in [2] i mean, it's explaining about total element of array, and [5] i mean, it's explaining about length of character in array
So, is it true how to use array 2 dimension in c ?
Sorry for my bad english
names is an array of two elements, each element is in turn an array of five elements.
And you use each array like you would any other. So the firs element of names is names[0], the second is names[1]. Then the first element of names[0] is names[0][0], the second names[0][1], etc.
Also, because each element of names is an array, and each of those two arrays are initialized as null-terminated strings, you can use names[0] and names[1] like any other string.
A multidimensional array is an array elements of which are in turn arrays.
Let's consider your declaration
char names[2][5] = {"john","boy"};
You can introduce a type alias like
typedef char T[5];
so the name T is an alias for the type char[5].
Now your initial declaration may be rewritten like
T names[2] = {"john","boy"};
That is you have an array of two elements which of them is in turn an array of the type char[5].
String literals are also have types of character arrays. For example the string literal "John" can be represented like
char john[5] = { 'J', 'o', 'h', 'n', '\0' };
elements of a string literal are used to initialize a corresponding character array.
So you array is initialized like
char names[2][5] = { { 'J', 'o', 'h', 'n', '\0' }, { 'b', 'o', 'y', '\0', '\0' } };
If a string literal contains less elements than the number of elements of the initialized array then all other elements of the array that have no an explicit initializer will be zero-initialized.
Consider a table of 2 * 5, where you get 2 rows, each of 5 columns. Here 2 dimensional array contains 2 rows i.e 2 char*. Each row is of size 5
Outputs:
names[0][0] = 'j'
names[1][0] = 'b'
name[0] = "john"
name[1] = "boy"
char names[2][5] = {"john","boy"};
names is a multi-dimensional char array with the height of 2 and the width 5:
__________________________________________________________________
│ j │ o │ h │ n │ \0 │ // 5 char elements, 1.dimension
│names[0][0]│ names[0][1]│ names[0][2]│ names[0][3] │ names[0][4] │
│___________│____________│____________│_____________│______________│
│ b │ o │ y │ \0 │ \0 │ // 5 char elements, 2.dimension
│names[1][0]│ names[1][1]│ names[1][2]│ names[1][3] │ names[1][4] │
│___________│____________│____________│_____________│______________│
Sorry, for the simple example but this might help you.

Understanding array manipulation pointers syntax in C

I have a struggle understanding a syntax of pointers, for example,
I have this code below:
void main(void)
{
char arr[][10] = {"It's", "wide", "and", "wonderful"};
printf("%c", (*arr)[3] - 1);
printf("%c", *arr[2] + 3);
}
I have no clue why it prints 'r' and 'd' like what's the whole process, I would kindly like an explanation.
This is obfuscation: code deliberately written to confuse.
*arr gives the first item (array) in your 2D array. At index 3 you find 's'. ASCII code for 's' - 1 = 'r'.
In *arr[2], the [] operator takes precedence, giving you the item at index 2 in your 2D array ("and"). * gives the contents of the first item (character) in that array, 'a'. ASCII code for 'a' + 3 = 'd'.
(Please note that arithmetic on symbol table values is not portable code. Only the digits 0 to 9 are guaranteed by the C standard to be placed adjacently in the symbol table.)
I'll break up the expressions (*arr)[3] - 1 and *arr[2] + 3 in order of precedence.
Expression (*arr)[3] - 1:
arr → {"It's", "wide", "and", "wonderful"}
(*arr) → "It's"
(*arr)[3] → 's'
(*arr)[3] - 1 → 'r'
Notice here two things: *arr is equivalent to arr[0], and you can perform arithmetic on a char, operating on the numeric value representing the character.
Expression *arr[2] + 3:
arr → {"It's", "wide", "and", "wonderful"}
arr[2] → "and"
*arr[2] → 'a'
*arr[2] + 3 → 'd'
The news here is that arr[] takes precedence over *arr, that is why the parenthesis is important in the first expression.
void main(void)
{
char arr[][10] = {"It's", "wide", "and", "wonderful"};
printf("%c", (*arr)[3] - 1); // arr[0][3] == the 4th char of the 1st string - 1 = s - 1 = r
printf("%c", *arr[2] + 3); // arr[2][0] == the 1st char of the 3rd string + 3 = a + 3 = d
}
in first case (*arr)[3] - 1
(*arr) gives us pointer to the first element of array: "It's"
(*arr)[3] gives us fourth element of "It's" which is: 's'
subtracting 1 from 's' gives us 'r'
in second case *arr[2]:
arr[2] gives us pointer to the third element of array: "and"
*arr[2] gives us first character of "and" which is 'a'
adding 3 to 'a' gives us 'd'
For (*arr)[3] - 1:
arr when treated like a pointer: the address of the first element. In this case, it is the address of "It's"
(*arr): dereferencing arr, aka "It's". And it's a char*
(*arr)[3]: the 4th character of "It's". The type is char
(*arr)[3] - 1: char can be used as a integer, so subtracting a char is subtracting its ASCII code. The value is 'r'
For *arr[2] + 3:
arr[2]: the 3rd element of arr (treated as an array), which is "and". The type is char*
*arr[2]: dereferencing "and", so 'a'
*arr[2] + 3: again ASCII code, its value is 'd'
Arrays used in expression are implicitly converted (with rare exceptions) to pointers to their first elements.
So if an array declared like this
char arr[4][10]
then this declaration you may rewrite like
char ( arr[4] )[10]
and in an expression the array designator is converted to pointer to its first element
char ( *p )[10]
So in this expression
(*arr)[3] - 1)
arr is converted to the type char ( * )[10] and points to the first string stored in the array. Applying the operator * you get the first sub-array (first string) that has the type char[10].
Applying the subscript operator you get the fourth character in the string that is equal to 's'. Now subtracting 1 you get the character 'r'.
In the second expression
*arr[2] + 3
that can be equivalently rewritten like
*( arr[2] ) + 3
you at first get the third sub-array of the array that is the sub-array with the string "and". This sub-array has the typechar[10]. Dereferencing the array designator (that is implicitly converted to pointer to its first element) you get the first character of the string that is'a'Adding to the character 3 you get the character'd'`.
The difference between the expressions is that in the first case you are dereferecing the array designator getting pointer to the first element and then applying the subscript operator for one-dimensional character array. In the second case you are first applying the subscript operator again getting one-dimensional array and then dereferencing the array designator that is implicitly converted to pointer to its fir element.
You should understand that if you have an array like for example
char s[] = "Hello";
then the expression *sis equivalent to *( &s[0] ) that is to s[0].
The expression *arr[2] is equivalent1),2) to arr[2][0] -
*arr[2] -> *(arr[2]) -> *((arr[2]) + 0) -> arr[2][0]
The expression (*arr)[3] is equivalent2) to arr[0][3] -
(*arr)[3] -> (*(arr + 0))[3] -> arr[0][3]
arr[0][3] represents 3rd character in first array which is s and arr[2][0] represents 0th character in third array which is a
The 2D array arr:
Array arr:
[0] = {
[0] = 'I'
[1] = 't'
[2] = '''
[3] = 's' ---> (*arr)[3], substrat 1 from s ==> r
[4] = '\0'
[5] = '\0'
[6] = '\0'
[7] = '\0'
[8] = '\0'
[9] = '\0'
}
[1] = {
[0] = 'w'
[1] = 'i'
[2] = 'd'
[3] = 'e'
[4] = '\0'
[5] = '\0'
[6] = '\0'
[7] = '\0'
[8] = '\0'
[9] = '\0'
}
[2] = {
[0] = 'a' --> *arr[2], add 3 to a ===> d
[1] = 'n'
[2] = 'd'
[3] = '\0'
[4] = '\0'
[5] = '\0'
[6] = '\0'
[7] = '\0'
[8] = '\0'
[9] = '\0'
}
[3] = {
[0] = 'w'
[1] = 'o'
[2] = 'n'
[3] = 'd'
[4] = 'e'
[5] = 'r'
[6] = 'f'
[7] = 'u'
[8] = 'l'
[9] = '\0'
}
}
1) The precedence of [] operator is higher than unary * operator.
2) C Standards#6.5.2.1
The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))..
First, let's note that *arr[2] is equivalent to *( arr[2] )
Secondly, keep in mind there is no difference between *(a + i) and a[i].
Thirdly, if there's no difference between *(a + i) and a[i], there's no difference between *a and a[0].
So,
(*arr)[3] === ( *( arr + 0 ) )[3] === arr[0][3]
The above produces the fourth character of the first string.
*arr[2] === *( arr[2] ) === *( arr[2] + 0 ) === arr[2][0]
The above produces the first character of the third string.

How do I edit a certain char in the following? [duplicate]

This question already has answers here:
how to replace a char in char *
(3 answers)
Closed 6 years ago.
So I have the following code:
char *something = (char *) calloc(LENGTH, sizeof(char));
The length is defined as 10.
I'm imaging it like this in memory:
| [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | \0 |
How would I change [1] without defining the whole char? And then be able to define [2], and so on...
Each change must not affect the previous change!
Thank you!
The length is defined as 10. I'm imaging it like this in memory
Incorrect. First, there are only 10 bytes (your picture shows 11) and second, all of them are filled with '\0' (which calloc() does).
How would I change [1] without defining the whole char? And then be able to define [2], and so on...
By "change" if you mean assigning values then you can index them like:
something[1] = 'a';
something[5] = 'q';
and so on.
But do remember, using it as a C-string may not work (for example, printing something using printf("%s", something);) since there are intermediate zero bytes.
Your code
char *something = (char *) calloc(LENGTH, sizeof(char));
gives you 10 (not 11) bytes, all initialised to 0.
You can change any byte in here you want
something[1] ='?';
If you use standard routine to e.g. printf this it will of course then find '0' in the first byte and interpret it as the end of a string.
Don't forget to free it when you are done
free(something);

Win32 API working with arrays

I'm beginner of programmer. I not understande why can't copy some script from array to another one.
char array1[11];
char array2[2];
array1 = {'255 105 85'};
array2[0] = array1[0];
array2[1] = array1[1];
array2[2] = array1[2];
MessageBox(hwnd,array2,"mes",NULL);
I was get "5" instead of "255".
I using the code::blocks with GCC complier.The project created with win32 frame based.
Somebody has idea what cause the problem?
The following construct is not allowed in C:
array1 = {'255 105 85'};
Instead you might consider using the static array initialization like this:
char array1[11] = {255, 105, 85};
This will fill the array1 with 3 specified values and leave all the other elements set to 0 (i.e. elements starting with index 3 and ending with index 10).
It's rather surprising, why the compiler didn't issue a syntax error in your case
updated:
Please also note that you are manipulating with individual characters when you have an expression like this array1[2]. If you want to operate on strings (i.e. have 3 separate strings for the numbers you have specified), you will have to declare something like this:
char *array1[3] = {
"255",
"105",
"85"
};
char *array2[3];
array2[0] = array1[0];
array2[1] = array1[1];
array2[2] = array1[2];
Thus you will have an array of strings. Each entry of array1 will contain a pointer (address) of the memory where string "255" is located (please note that "255" is an array comprising 4 chars: '2', '5', '5', '\0').
Array1 should be declared like this:
char array1[] = {0x255, 0x105, 0x85};
single quotes are for single chars in ascii, like 'a' or '6' or '!'.
Also, array2 is of length 2, but you are assigning a value to the third value (array2[2]). This is probably an error.

Trouble with array pointers in C

I was solving last years GATE question paper where i am stuck with this question
What does the following fragment of C-program print?
char c[]="GATE2011";
char *p =c;
printf ("%s", p+p[3]-p[1]);
The answer is '2011'
I am aware that in c, array variables are pointer to first address of the array. My logical answer was 'E2011', but the output is 2011
Can someone explain the pointer mathematics involved in this?
This problem has much more to do with ASCII values than it does with pointers.
p[3] == 'E' == 69 (decimal)
p[1] == 'A' == 65
p[3]-p[1] = 4
p+4 = A string starting at the 4th character.
p[] = [0] [1] [2] [3] [4] [5] [6] [7] [8]
G A T E 2 0 1 1 \0
Hence, p[4] = 2011
p[3] = A
p[1] = E
E - A = 4
hence p + 4 = address of 2
hence it prints 2011

Resources