I'm not sure how to approach this but put simply, a part of my homework states that I need to check if an array has at least 3 stored integer values and display an error message if it has less. The other part is getting the sum of all values in the array and show the output in the console.
I'm using RARS and the array is already declared in .data along with its values.
Arrays have a notion of length, which can be in bytes, or in element count, but unlike Java and C#, there is no standardized way to represent this notion of length in assembly language or in C code.
Sometimes the length is represented in the program by a constant.
Sometimes the length is represented in the program by a variable, more or less directly as a count of elements (though a program variable could also be an index referring to the last element, in which case that count is that variable + 1).
Sometimes the length is represented in the program by an end pointer — a pointer one element past the last, and also the place to store the next element, if one comes, when growing the array in place is possible.
Sometimes the length is encoded as a special element value, a sentinel or terminator, and to find the length one traverses forwards until that element is found — there must be sufficient storage to hold the real elements and the sentinel as well but it not considered an element of the array.
C-style strings are arrays of character, nul-terminated, so use the special character nul aka `\0' or just 0 as the terminator.
We can also pair a length value with a pointer value to compose a higher level notion of array with length into an object or structure.
This is not necessarily a complete list, since programmers can do as they like. (Other schemes are possible, such as storing the length at the beginning of the array, or in front of the array, i.e. at position -1 in the array).
A function taking an array as a parameter will often also take another parameter that is the length, but in the case of int main(int argc, char *argv[]) we see the length being passed as the first parameter and the array as the second..
It would be a logic error for a program to have an array whose length is unknown and not computable.
You will need to determine the method for representing the length, and then compare the length with your constant 3 as required.
For example, if the method is an end pointer, then you can subtract: end pointer - beginning pointer (the array base, or address of first element), and then divide that result by the array's element size, which will yield a count of the number of elements.
Related
This is a code I have used to define an array:
int characters[126];
following which I wanted to get a record of the frequencies of all the characters recorded for which I used the while loop in this format:
while((a=getchar())!=EOF){
characters[a]=characters[a]+1;
}
Then using a for loop I print the values of integers in the array.
How exactly is this working?
Does C assign a specific number for letters ie. a,b,c, etc in the array?
What happens when we make an array defined using characters instead of integers in C?
Let's be sure we are clear: you are using integer values returned by getchar() as indexes into your array. This is not defining the array, it is just accessing its elements.
Does C assign a specific number for letters ie. a,b,c, etc in the array?
There are no letters in the array. There are ints. However, yes, the characters read by getchar() are encoded as integer values, so they are, in principle, suitable array indexes. Thus, this line ...
characters[a]=characters[a]+1;
... reads the int value then stored at index a in array characters, adds 1 to it, and then assigns the result back to element a of the array, provided that the value of a is a valid index into the array.
More generally, it is important to understand that although one of its major uses is to represent characters, type char is an integer type. Its values are numbers. The mapping from characters to numbers is implementation and context dependent, but it is common enough for the mapping to be consistent with the ASCII code that you will often see programs that assume such a mapping.
Indeed, your code makes exactly such an assumption (and others) by allowing only for character codes less than 126.
You should also be aware that if your characters array is declared inside a function then it is not initialized. The code depends on all elements to be initially to zero. I would recommend this declaration instead:
int characters[UCHAR_MAX + 1] = {0};
That upper bound will be sufficient for all the non-EOF values returned by getchar(), and the explicit zero-initialization will ensure the needed initial values regardless of where the array is declared.
I have realized the charecter set that can function as an input for getchar() is part of the ASCII table and comes under an int. I used the code following to find that out:
#include <stdio.h>
int main(){
int a[128];
a['b']=4;
printf("%d",a[98]); //it is 98 as according to the table 'b' is assigned the value of 98
}
following which executing this code i get the output of 4.
I am really new to coding so feel free to correct me.
Character values are represented using some kind of integer encoding - ASCII (very common), EBCDIC (mostly IBM mainframes), UTF-8 (backward-compatible to ASCII), etc.
The character value 'a' maps to some integer value - 97 in ASCII and UTF-8, 129 in EBCDIC. So yes, you can use a character value to index into an array - arr['a']++ would be equivalent to arr[97]++ if you were using ASCII or UTF-8.
The C language does not dictate this - it's determined by the underlying platform.
I'm making a simple program in C, which checks the length of some char array and if it's less than 8, I want to fill a new array with zeroes and add it to the former array. Here comes the problem. I don't know why the last values are some signs(see the photo).
char* hexadecimalno = decToHex(decimal,hexadecimal);
printf("Hexadecimal: %s\n", hexadecimalno);
char zeroes [8 - strlen(hexadecimalno)];
if(strlen(hexadecimalno) < 8){
for(i = 0; i < (8-strlen(hexadecimalno)); i++){
zeroes[i]='0';
}
}
printf("zeroes: %s\n",zeroes);
strcat(zeroes,hexadecimalno);
printf("zeroes: %s\n",zeroes);
result
In C, strings (which are, as you are aware, arrays of characters) do not have any special metadata that tells you their length. Instead, the convention is that the string stops at the first character whose char value is 0. This is called "null-termination". The way your code is initializing zeroes does not put any null character at the end of the array. (Do not confuse the '0' characters you are putting in with NUL characters -- they have char value 48, not 0.)
All of the string manipulation functions assume this convention, so when you call strcat, it is looking for that 0 character to decide the point at which to start adding the hexadecimal values.
C also does not automatically allocate memory for you. It assumes you know exactly what you are doing. So, your code is using a C99 feature to dynamically allocate an array zeroes that has exactly the number of elements as you need '0' characters appended. You aren't allocating an extra byte for a terminating NUL character, and strcat is also going to assume that you have allocated space for the contents of hexadecimalno, which you have not. In C, this does not trigger a bounds check error. It just writes over memory that you shouldn't actually write over. So, you need to be very careful that you do allocate enough memory, and that you only write to memory you have actually allocated.
In this case, you want hexadecimalno to always be 8 digits long, left-padding it with zeroes. That means you need an array with 8 char values, plus one for the NUL terminator. So, zeroes needs to be a char[9].
After your loop that sets zeroes[i] = '0' for the correct number of zeroes, you need to set the next element to char value 0. The fact that you are zero-padding confuses things, but again, remember that '0' and 0 are two different things.
Provided you allocate enough space (at least 9 characters, assuming that hexadecimalno will never be longer than 8 characters), and then that you null terminate the array when putting the zeroes into it for padding, you should get the expected result.
This question already has answers here:
How do I determine the size of my array in C?
(24 answers)
Closed 6 years ago.
my professor has assigned a project where we need to make a reverse polish calculator in C (input in postscript syntax). I'm currently working on a method to find the length of the array of values I have scanned in (via .txt file). My current method is
int length(int list[]) {
int c = 0;
while(0 == 0) {
if(list[c] != '\0') {c++;}
else {break;}
}
return c;
}
and the call for it is
int sizeA = length(list);
printf("\n%d\n", sizeA);
It's currently only outputting the length as 0. Does anyone know why that might be and a fix to this method?
Thanks
The notion of "length" is a sort of tricky one in C (and low-level programming in general). If you have an array, the C compiler knows how large it is and provides an interface to the programmer to get that value in bytes: sizeof. The thing is, arrays are passed via pointers in C and determining the size via pointers is impossible without certain meta-information. Common methods to determine the length of an array are
appending an end marker to the array. Determining the length is simply a matter of iterating until the end marker is found and returning the number of iterations. Note that this renders the end marker's value unavailable for use as a value in the array.
just passing the size of the array around. Take the write system call as an example. Besides the file handle, it needs a pointer to the data and its length. Why its length as well? Because the pointer doesn't contain information about the length. So, either use a terminator like a null byte or pass the length explicitly. The former idea can be abandoned because the write system call is supposed to be generic; and to yield genericity, a null byte must be expected to be a possible value in the array, so it cannot be used as a terminator for reasons I uttered above.
Which one you actually end up using totally depends on the particular use case.
Apparently you decided to use the terminator-variant. \0 is the null byte, an ASCII character with code value 0x0. It's commonly used for terminating C-strings. strlen uses it to determine a C-string's length, for example. For int arrays, there is no such predefined terminator, so you need to come up with your own one. If you decide on \0, so be it, but I'd use the literal 0x0 instead because strictly-speaking, \0 is a character literal and that's just unfitting for ints.
To actually implement this, you'd need to append the terminating value to every int array, whose size you want to determine this way. Then write your function to get the length of such an int array just as you do, i.e., by iterating until the terminator is found.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I tried to populate an array of structs defined as follows:
typedef struct{
char directive[5];
}directive_nfo_t;
By using the following:
directive_nfo_t directive_list[]=
{
{"ALIGN"},{"ASCII"},{"BSS"},{"BYTE"},{"END"},{"EQU"},{"ORG"}
};
To my surprise, the first few elements were corrupted like so:
[0]= ALIGNASCIIBSS
[1]= ASCIIBSS
[2]= BSS
...
Until I made the following change:
typedef struct{
char directive[6]; <-- made char array +1
}directive_nfo_t;
Then the first few arrays were correct like so:
[0]= ALIGN
[1]= ASCII
[2]= BSS
...
My question is what happens in the background to explain this behavior?
Regards.
In C, a string is a sequence of character values followed by a 0-valued terminator; the string "ASCII" is represented by the character sequence 'A', 'S', 'C', 'I', 'I', 0. Thus, you need a six-element array to store the string.
For a string that's N characters long, you need an array of N+1 characters to store it.
When you explicitly initialize a char array as string literal in the way you do:
char some_array[] = {"ALIGN"};
the compiler actually populates the 0th to 4th "position" (total of 5 positions) with the characters inside quotation marks, but also the fifth position with \0 without requiring you do it explicitly (if it has space enough). So the size equals 6. You exceed the boundaries if you don't count the \0 character into the size calculation and restrict the size to 5. Compiler would omit the terminating character.
In your case it looks as if the first element of the next member "overwrote" what should have been the omitted \0 character of the previous, since you haven't reserved a place for it. In fact the "mechanics of populating the array" boils down to the compiler writing as much data as could fit inside the boundaries. The address of the first position of the next member string logically corresponds to your assignment, although the \0 from the previous is missing.
Since your printf() format tag was %s, the function printed the characters until it reached the first \0 character, which is in fact undefined behavior.
That's why
char directive[6];
was correct size assignment in your code.
If the char array is big enough, C compiler automatically places a '\0' after the text.
If it is just large enough for the text, that terminator is omitted, which is what has happened here.
If there isn't even room for the text, the compiler will say something like "too many initialisers" or "array bounds overflow".
The struct array elements are adjacent in memory. The first two items lack a terminator, so the second item printed only stops at the terminator after the third item. The first item, is also printed until it reaches that same terminator. By making the array size 6, the compiler was able to place a terminator after every item.
Unlike in C++, C allows you to (unintentionally) shoot yourself in the feet, by allowing to omit NUL terminating character '\0' in the char array initializer when there is no room for it. Your case can be narrowed down to a simple array definition such as:
char str[5] = "ALFAP";
which is a syntatic shortcut to:
char str[5] = {'A', 'L', 'F', 'A', 'P'};
It may be kind of misleading, because in different context the same "ALFAP" represets string literal, that always has the ending NUL character:
char* str = "ALFAP" // here, "ALFAP" always contains NUL character at the end
My question is what happens in the background to explain this behavior? Regards.
You have an array of struct directive_nfo_t type and each struct directive_nfo_t holds array of five characters (in your first example).
The output that you were getting when you have 5 character array in directive_nfo_t type was basically due to two things-
Array elements are stored in consecutive memory locations.
In C, the abstract idea of a string is implemented with just null terminated array of characters.
When you have declared an array of directive_nfo_t type, each element of directive_nfo_t is stored in consecutive memory location and each element has 5 character array(which are also stored in consecutive locations) in it. And in your Initialization list({"ALIGN"},{"ASCII"},{"BSS"},{"BYTE"},{"END"},{"EQU"},{"ORG"}) for the array, you have used all the 5 characters in storing your data in first two elements of directive_nfo_t ("ALIGN" and "ASCII"). As, in C, functions which operate on character array to implement abstract idea of string, assume that a string will be terminated by using a null character at the end. Therefore, in the first two elements of directive_nfo_t array, the printf will keep on printing characters until it reaches null character(which it will find in element storing character array "BSS"). After printing ALIGN, printf will access the first character of second element of the array of directive_nfo_t (character A of ASCII). It occurred because there was not space for null character in the first element of array of directive_nfo_t type and compiler wouldn't add characters beyond array size as it does array bound check. From the third element of you array, you have enough space for null character and hence, printf works as expected.
You will get UNDEFINED BEHAVIOR if you allocate less memory to store your character array and use those functions which assume null terminated character array. Always set the size of the character array to MAX + 1 when you want to store maximum MAX characters in your array.
I've been comparing the two statements, which use fgets to read a string from standard input.
char array[10];
fgets(array, sizeof(array), stdin) ;
fgets(array, (sizeof(array)/sizeof(array[0])) , stdin);
Technically, both are identical, with the exception that method 2 is redundant, since fgets can only accept a char array.
My thought process is that since fgets takes a char *s argument there isn't any need for the second example(chars are one byte, so division by 1 is redundant) .
However, when dealing with arrays of a different data type (in a for loop for example), the second method of determining the size of the array is required.
The second statement looks ugly, but are there any other major disadvantages of using it? Here are some advantages I can think of:
Teaches correct way of determining array sizes for other applications, e.g. for for() loops.
Does not break down if (not applicable for this example, as fgets only takes char arrays) the array type is changed
The second form, shown below, could get you an unpleasant surprise.
fgets(array, (sizeof(array)/sizeof(array[0])) , stdin);
Specifically, the second argument to fgets represents the maximum number of char values (less 1 for the trailing NUL) which array can hold.
So, if array is declared as
char array[SOME_NUMBER];
Then sizeof(array)/sizeof(array[0]) would yield SOME_NUMBER. But what if it were defined as one of the following:
int array[SOME_NUMBER];
char array[SOME_NUMBER][SOME_OTHER_NUMBER];
In the both cases, it would yield SOME_NUMBER because it calculates the number of elements in the array. But it completely ignores the size of each element. Imagine in the second case that SOME_NUMBER was significantly larger than SOME_OTHER_NUMBER. The fgets would fill the first element of array and then overflow into one or more of the subsequent elements. Here you really wanted to pass in SOME_OTHER_NUMBER.
The take-away here is that you need to be explicit in the value you pass to fgets. For the normal case (a single-dimension char array), sizeof(array) is fine. For an array of char arrays (as shown above), then either SOME_OTHER_NUMBER or sizeof(array[0]) should be used.
The sizeof(array)/sizeof(array[0]) approach should never be used, because it is not calculating a size which inherently relates to sizeof(char). It is calculating the number of elements in array - regardless of their size.