Question

1. The code below compiles and runs, but the compiler should issue a warning about the toString(...) function. Even if your compiler does not issue a warning, it certainly should do so. What is the problem with my toString(...)? If you run the code, it seems to work just fine.

/** Should compile (with a warning) but run. **/
#include <stdio.h>
#include <string.h>

#define MaxBuffer 64

typedef struct Emp {
char    lname[MaxBuffer + 1];
char    fname[MaxBuffer + 1];
char    mi;
unsigned dept;
unsigned id;
float    sal;
} Emp;

const char* toString(const Emp* emp) {
char buffer[MaxBuffer * 10]; /* make it plenty big */
char local[MaxBuffer + 1];
memset(buffer, 0, sizeof(buffer)); /* zero out buffer */
memset(local, 0, sizeof(local));    /* ditto */

/** Stringify the Emp object with human-readable information. **/
strcpy(buffer, "Employee information:\n");
sprintf(local, "\tID:   %i\n", emp->id);
strcat(buffer, local);
sprintf(local, "\tName: %s %c. %s\n", emp->fname, emp->mi, emp->lname);
strcat(buffer, local);
sprintf(local, "\tDept: %i\n", emp->dept);
strcat(buffer, local);
sprintf(local, "\tSal: %f\n", emp->sal);
strcat(buffer, local);
return buffer;
}

int main() {
Emp fred;
memset(&fred, 0, sizeof(fred)); /* zero out the fred structure */
/* Populate the members with data. */
strncpy(fred.lname, "Flintstone", strlen("Flintstone"));
strncpy(fred.fname, "Fred", strlen("Fred"));
fred.mi = 'J';
fred.dept = 27;
fred.id = 1234;
fred.sal = 31514.00f;
printf("%s\n", toString(&fred)); /* invoke toString(...) */

return 0;
}

2. (a) Amend the toString.c program from Question 1 by rewriting toString(...) so that the problem in the current version is fixed. The return type (const char*) should remain the same, but you may make whatever other changes you like. The output should be the same as in the original. Explain exactly why your rewrite is an improvement over the original: this can be done in the documentation.

The amended code should be in its own file, together with my main: you can comment out or delete my (bad) version of toString(...).

(b) In main, memset is called to zero out the Emp structure identified as fred. In the gif2cymk function, memset is called twice. Why is this a good idea inthis example and in general?

3. Here is a program that invokes the gif2cymk function, which converts a GIF value into a CYMK one. Modern printers often use CYMK encodings to print images:

#include <stdio.h>

void rgb2cmyk(int r, int g, int b, int ret[]) {
int c = 255 - r;
int m = 255 - g;
int y = 255 - b;
int k = (c < m) ? (c < y ? c : y) : (m < y ? m : y);
c -= k;
m -= k;
y -= k;
ret[0] = c; ret[1] = m; ret[2] = y; ret[3] = k;
}

int main() {
int red = 188, green = 143, blue = 143; /* rosy red in GIF */
int cmyk[4]; /* Cyan, Magenta, Yellow, and blacK values */
rgb2cmyk(red, green, blue, cmyk);
printf("Rosy red in CMYK:\n");
printf("C: %2i\nM: %2i\nY: %2i\nK: %2i\n",
cmyk[0], cmyk[1], cmyk[2], cmyk[3]); /* 0 45 45 67 */
return 0;
}

The code compiles and runs without issue.

Below are two copies of assembly code generated from the compilation of the gif2cymk function alone. For reference, the first is color1.s and the second is color2.s. There is no need to do a line-by-line documentation of the code. Rather, use the assembly code listings to answer the following questions:

(a) What do you see as the essential difference between the two versions?
(b) Which version is better, and why? Be as specific as possible in justifying your answer.

#### color1.s
.file "color1.c"
.text
.globl rgb2cmyk
.type rgb2cmyk, @function
rgb2cmyk:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $16, %esp
movl $255, %eax
subl 8(%ebp), %eax
movl %eax, -16(%ebp)
movl $255, %eax
subl 12(%ebp), %eax
movl %eax, -12(%ebp)
movl $255, %eax
subl 16(%ebp), %eax
movl %eax, -8(%ebp)
movl -16(%ebp), %eax
cmpl -12(%ebp), %eax
jge .L2
movl -16(%ebp), %eax
cmpl %eax, -8(%ebp)
cmovle -8(%ebp), %eax
jmp .L3
.L2:
movl -12(%ebp), %eax
cmpl %eax, -8(%ebp)
cmovle -8(%ebp), %eax
.L3:
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
subl %eax, -16(%ebp)
movl -4(%ebp), %eax
subl %eax, -12(%ebp)
movl -4(%ebp), %eax
subl %eax, -8(%ebp)
movl 20(%ebp), %eax
movl -16(%ebp), %edx
movl %edx, (%eax)
movl 20(%ebp), %eax
leal 4(%eax), %edx
movl -12(%ebp), %eax
movl %eax, (%edx)
movl 20(%ebp), %eax
leal 8(%eax), %edx
movl -8(%ebp), %eax
movl %eax, (%edx)
movl 20(%ebp), %eax
leal 12(%eax), %edx
movl -4(%ebp), %eax
movl %eax, (%edx)
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
######

#### color2.s

.file "color2.c"
.text
.globl rgb2cmyk
.type rgb2cmyk, @function
rgb2cmyk:
.LFB0:
.cfi_startproc
pushl %esi
.cfi_def_cfa_offset 8
.cfi_offset 6, -8
pushl %ebx
.cfi_def_cfa_offset 12
.cfi_offset 3, -12
movl 24(%esp), %eax
movl $255, %ebx
movl %ebx, %esi
subl 12(%esp), %esi
movl %ebx, %ecx
subl 16(%esp), %ecx
subl 20(%esp), %ebx
cmpl %ecx, %esi
jge .L2
cmpl %ebx, %esi
movl %ebx, %edx
cmovle %esi, %edx
jmp .L3
.L2:
cmpl %ebx, %ecx
movl %ebx, %edx
cmovle %ecx, %edx
.L3:
subl %edx, %esi
movl %esi, (%eax)
subl %edx, %ecx
movl %ecx, 4(%eax)
subl %edx, %ebx
movl %ebx, 8(%eax)
movl %edx, 12(%eax)
popl %ebx
.cfi_restore 3
.cfi_def_cfa_offset 8
popl %esi
.cfi_restore 6
.cfi_def_cfa_offset 4
ret
.cfi_endproc

4. Below is an assembly-language program that compiles and runs on a 64-bit Intel machine. Two lines in the code need to be explained. See the code documentation for the particulars.

### Yet another "Hello, world!" in assembly language.
##
## The register %rip is the "program counter" or, in Intel-speak,
## the "instruction pointer": whatever the name, %rip holds the
## address of the next instruction to execute.
## In the code below, one line is marked EXPLAIN. In particular,
## explain in detail how the first operand to leaq--the operand
## hello(%rip)--works in this example. You can explain in words,
## in pictures, or in a mix of the two--whatever it takes to show
## that you understand how this particular line works.
##
## One more line, ALSO EXPLAIN, requires explanation. This should
## be more straightforward.
.data
hello:
.ascii "Hello, world!\n"
.text
.globl main
main:
subq $8, %rsp

movb $0, %al            ## %al = "low" order bits in %rax == %eax
leaq hello(%rip), %rdi ## EXPLAIN
call printf

movq $0, %rdi          ## ALSO EXPLAIN
call exit

Solution Preview

This material may consist of step-by-step explanations on how to solve a problem or examples of proper writing, including the use of citations, references, bibliographies, and formatting. This material is made available for the sole purpose of studying and learning - misuse is strictly forbidden.

/*2. My improvement is the change the buffer from a char of a specific size to a char pointer which needs to be returned
* This allows for the same size array, but now it is specifically writing to memory that won't lose its data
* once the function is exited and the scope changes.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MaxBuffer 64

typedef struct Emp {
char    lname[MaxBuffer + 1];
char    fname[MaxBuffer + 1];
char    mi;
unsigned dept;
unsigned id;
float    sal;
} Emp;

const char* toString(const Emp* emp) {
char *buffer = (char*)malloc(MaxBuffer * 10); /* make it plenty big */
char local[MaxBuffer + 1];
memset(buffer, 0, sizeof(buffer)); /* zero out buffer */
memset(local, 0, sizeof(local));    /* ditto */

/** Stringify the Emp object with human-readable information. **/
strcpy(buffer, "Employee information:\n");
sprintf(local, "\tID:   %i\n", emp->id);
strcat(buffer, local);
sprintf(local, "\tName: %s %c. %s\n", emp->fname, emp->mi, emp->lname);
strcat(buffer, local);
sprintf(local, "\tDept: %i\n", emp->dept);
strcat(buffer, local);
sprintf(local, "\tSal: %f\n", emp->sal);
strcat(buffer, local);
return buffer;
}

int main() {
Emp fred;
memset(&fred, 0, sizeof(fred)); /* zero out the fred structure */
/* Populate the members with data. */
strncpy(fred.lname, "Flintstone", strlen("Flintstone"));
strncpy(fred.fname, "Fred", strlen("Fred"));
fred.mi = 'J';
fred.dept = 27;
fred.id = 1234;
fred.sal = 31514.00f;
printf("%s\n", toString(&fred)); /* invoke toString(...) */

return 0;
}...

This is only a preview of the solution. Please use the purchase button to see the entire solution

Related Homework Solutions

Get help from a qualified tutor
Live Chats