Code

การทดสอบนี้ อาจจะขึ้นอยู่กับตัวแปรหลายอย่าง เช่น compiler,OS,version หรืออื่นๆ
การทดลองนี้ใช้ Ubunti 12.04LTS โดยใช้ gcc ในการ compile โดยไม่ได้ optimize ใดๆ
#include <stdio.h>
int main()
{
  int *pa, i, a[10];

  for (i = 0; i < 10;i++)
    a[i] = 100;
  for (pa = a; pa < a + 10; pa++)
    *pa = 100;
  return 0;
}
ใช้ gcc ทำการ compile code ออกมาเป็น assembly(AT&T) จะได้
	.file	"test.c"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$48, %esp
	movl	$0, -4(%ebp)
	jmp	.L2
.L3:
	movl	-4(%ebp), %eax
	movl	$100, -48(%ebp,%eax,4)
	addl	$1, -4(%ebp)
.L2:
	cmpl	$9, -4(%ebp)
	jle	.L3
	leal	-48(%ebp), %eax
	movl	%eax, -8(%ebp)
	jmp	.L4
.L5:
	movl	-8(%ebp), %eax
	movl	$100, (%eax)
	addl	$4, -8(%ebp)
.L4:
	leal	-48(%ebp), %eax
	addl	$40, %eax
	cmpl	%eax, -8(%ebp)
	jb	.L5
	movl	$0, %eax
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
	.section	.note.GNU-stack,"",@progbits
Array
จะเห็นว่า .L2 จะเป็นการเริ่มต้นการทำงานในของลูป
for (i = 0; i < 10;i++)
จะเห็น
cmpl $9, -4(%ebp)
มีการเปรียบเทียบค่าทันที ถ้าน้อยกว่าก็จะทำการ jump ไปที่ .L3 ทันที
 
Pointer
จะเห็นว่า .L4 จะเป็นการเริ่มต้นการทำงานในของลูป  
for (pa = a; pa < a + 10; pa++)
จะเห็น
leal -48(%ebp), %eax
addl $40, %eax
cmpl %eax, -8(%ebp)
ก่อนจะมีการเปรียบเทียบค่า จะมี 2 instruction set ที่ทำงานก่อนที่จะมีการเปรียบเทียบค่า หลังจากที่เปรียบค่า ถ้าจริงก็จะ jump ไปที่ .L5 ทันที
 
สรุป
Array เร็วกว่า Pointer.

อ้างอิงจาก http://stackoverflow.com/questions/2305770/efficiency-arrays-vs-pointers

edit @ 20 Sep 2013 21:27:09 by s4m3l0

compile curlgtk on ubuntu 12.04TLS

posted on 13 Sep 2013 16:31 by s4m3l0 in Code directory Knowledge, Diary
/*****************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 */ 
/* Copyright (c) 2000 David Odin (aka DindinX) for MandrakeSoft */ 
/* an attempt to use the curl library in concert with a gtk-threaded application */ 
 
#include <stdio.h>
#include <gtk/gtk.h>
 
#include <curl/curl.h>
 
GtkWidget *Bar;
 
size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
  return fwrite(ptr, size, nmemb, stream);
}
 
size_t my_read_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
  return fread(ptr, size, nmemb, stream);
}
 
int my_progress_func(GtkWidget *bar,
                     double t, /* dltotal */ 
                     double d, /* dlnow */ 
                     double ultotal,
                     double ulnow)
{
/*  printf("%d / %d (%g %%)\n", d, t, d*100.0/t);*/ 
  gdk_threads_enter();
  gtk_progress_set_value(GTK_PROGRESS(bar), d*100.0/t);
  gdk_threads_leave();
  return 0;
}
 
void *my_thread(void *ptr)
{
  CURL *curl;
  CURLcode res;
  FILE *outfile;
  gchar *url = ptr;
 
  curl = curl_easy_init();
  if(curl)
  {
    outfile = fopen("test.curl", "w");
 
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func);
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_read_func);
    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
    curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);
    curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, Bar);
 
    res = curl_easy_perform(curl);
 
    fclose(outfile);
    /* always cleanup */ 
    curl_easy_cleanup(curl);
  }
 
  return NULL;
}
 
int main(int argc, char **argv)
{
  GtkWidget *Window, *Frame, *Frame2;
  GtkAdjustment *adj;
 
  /* Must initialize libcurl before any threads are started */ 
  curl_global_init(CURL_GLOBAL_ALL);
 
  /* Init thread */ 
  g_thread_init(NULL);
 
  gtk_init(&argc, &argv);
  Window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  Frame = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(Frame), GTK_SHADOW_OUT);
  gtk_container_add(GTK_CONTAINER(Window), Frame);
  Frame2 = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(Frame2), GTK_SHADOW_IN);
  gtk_container_add(GTK_CONTAINER(Frame), Frame2);
  gtk_container_set_border_width(GTK_CONTAINER(Frame2), 5);
  adj = (GtkAdjustment*)gtk_adjustment_new(0, 0, 100, 0, 0, 0);
  Bar = gtk_progress_bar_new_with_adjustment(adj);
  gtk_container_add(GTK_CONTAINER(Frame2), Bar);
  gtk_widget_show_all(Window);
 
  if (!g_thread_create(&my_thread, argv[1], FALSE, NULL) != 0)
    g_warning("can't create the thread");
 
 
  gdk_threads_enter();
  gtk_main();
  gdk_threads_leave();
  return 0;
}
sudo apt-get install libgtk2.0-dev libcurl4-openssl-dev
gcc curlgtk.c $(pkg-config --cflags --libs gtk+-2.0 libcurl gthread-2.0) -o curlgtk

edit @ 13 Sep 2013 16:39:16 by s4m3l0

เนื่องจากอ่าน code ภาษา C โดยทั่วไป(textbook,stackoverflow) จะไม่ค่อยได้เจอคำว่า volatile เท่าไร กับประสบการณ์อันน้อยนิด ทำให้ทำข้อสอบข้อนี้ไม่ได้
แต่พอไปหาบทความเรื่องนี้ ก็ไปเจอ
แล้วก็ไปเจอ http://lwn.net/Articles/233482/ จากการอ้างอิงบทความข้างต้น ได้ใจความว่า...
 
If the memory barriers are right, then the "volatile" doesn't matter.

And if the memory barriers aren't right, then "volatile" doesn't help.

Using "volatile" in data structures is basically _always_ a bug.

The only acceptable uses for "volatile" are:

 - in _code_, i.e., for things like the definition of "readb()" etc, where we
   use it to force a particular access.
 - with inline asms
 - on "jiffies", for stupid legacy reasons

Basically, a volatile on a data structure can NEVER be right. If it makes
a difference, it's a sign of improper locking.

And the reason I refuse to apply that part of the patch is that anybody
who even _thinks_ that they make a difference is horribly and utterly
confused, and doesn't understand locking.

So please _never_ use them like this.
สรุปง่ายๆ ถ้ากำหนดพวก memory barriers ถูกต้อง volatile ก็ไม่สำคัญ และก็ไม่ควรใช้เป็นอย่างยิ่ง Foot in mouth
แต่ใช้แค่ในบางโอกาศเท่านั้น ที่จำเป็นจริงๆ ที่เมื่อไม่ต้องการให้ compiler ขณะที่ compile แบบ optimize code ทำการเปลี่ยนตัวแปรดังเดิมที่ประกาศไว้
ทำให้ทำข้อนี้ไม่ได้ เลยปล่อยว่างทั้งข้อเลย Tongue out